Skip to content

Latest commit

 

History

History
847 lines (703 loc) · 26 KB

File metadata and controls

847 lines (703 loc) · 26 KB

Emacs Configurations

Introduction

An Emacs configuration for note taking, documenting and development. Clone using:

git clone https://github.com/madhavan-raja/emacs-config.git ~/.emacs.d

Open README.org in Emacs and run:

(org-babel-tangle)

Lastly, restart Emacs.

Table of Contents

Packages

We set up melpa, use-package, and straight.el for installing package later on. Melpa has a lot more packages than the default elpa. Use-package is pretty useful (pun intended) since packages can be automatically installed and lazy-loaded. Straight.el is for downloading packages from git repos. We also install the package auto-package-update to update installed packages.

(require 'package)

(setq package-archives '(("gnu" . "http://elpa.gnu.org/packages/")
                         ("melpa" . "http://melpa.org/packages/")))

(package-initialize)
(unless package-archive-contents
  (package-refresh-contents))

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))
(require 'use-package)

(setq use-package-always-ensure t)
(setq package-enable-at-startup nil)

(use-package auto-package-update
   :ensure t
   :config
   (setq auto-package-update-delete-old-versions t
         auto-package-update-interval 4)
   (auto-package-update-maybe))

Window

Set window title, start the application maximized and disable the startup screen.

(setq frame-title-format "%b - Emacs")
(add-to-list 'default-frame-alist '(fullscreen . maximized))
(setq ring-bell-function 'ignore)

Behaviour

Basic Settings

(setq-default
  delete-by-moving-to-trash t ;; Move to trash instead of deleting
  require-final-newline t ;; Auto create a newline at end of file
  custom-safe-themes t ;; Don't ask if theme is safe
  warning-minimum-level :emergency ;; Emacs, honestly, I want you to shut up
  disabled-command-function nil ;; Yes I want to use that command
  vc-follow-symlinks) ;; Follow those damn symlinks!

(defalias 'yes-or-no-p 'y-or-n-p) ;; Y or N instead of yes or no

(setq scroll-margin 1
  scroll-step 1
  scroll-conservatively 10000
  smooth-scroll-margin 1)

Backup Files

Disable the generation of backup files.

(setq make-backup-files nil)

Notifications

Disable the notifications.

(setq ring-bell-function 'ignore)

Esc cancels the current command

Map the escape key to cancel the current command. Useful with evil-mode.

(global-set-key (kbd "<escape>") 'keyboard-escape-quit)

Custom File

Set the location of the custom files to .custom directory.

(setq custom-file (expand-file-name ".custom" user-emacs-directory))

Theme

(use-package doom-themes
  :config
  (load-theme 'doom-gruvbox t)
  (doom-themes-neotree-config))

Basic Visual Adjustments

Disable the scroll bar, menu bar, tool bar, tooltips, and the start screens

(scroll-bar-mode -1)
(menu-bar-mode -1)
(tool-bar-mode -1)
(tooltip-mode -1)
(setq inhibit-splash-screen nil
  inhibit-startup-echo-area-message t
  inhibit-startup-message t)

Prettify Things

This replaces some text with icons. Also ligatures.

(defun org/prettify-set ()
  (interactive)
  (setq prettify-symbols-alist
      '(("#+begin_example" . "")
        ("#+BEGIN_EXAMPLE" . "")
        ("#+end_example" . "")
        ("#+END_EXAMPLE" . "")
        ("#+results:" . "")
        ("#+RESULTS:" . "")
        ("#+begin_quote" . "")
        ("#+BEGIN_QUOTE" . "")
        ("#+end_quote" . "")
        ("#+END_QUOTE" . "")
        ("[ ]" . "")
        ("[-]" . "")
        ("[X]" . ""))))
(add-hook 'org-mode-hook 'org/prettify-set)

(defun prog/prettify-set ()
  (interactive)
  (setq prettify-symbols-alist
      '(("lambda" . "λ")
        ("->" . "")
        ("<-" . "")
        ("<=" . "")
        (">=" . "")
        ("!=" . "")
        ("~=" . "")
        ("=~" . ""))))
(add-hook 'prog-mode-hook 'prog/prettify-set)

(global-prettify-symbols-mode)

Line Numbers

Display line numbers when programming.

(global-display-line-numbers-mode)
(setq display-line-numbers-type 'relative)

And sometimes line numbers can be distracting, so we disable them for certain modes.

(dolist (mode '(org-mode-hook
  term-mode-hook
  eshell-mode-hook
  neotree-mode-hook
  elfeed-show-mode-hook
  circe-channel-mode-hook
  circe-chat-mode-hook
  doc-view-mode-hook
  xwidget-webkit-mode-hook
  woman-mode-hook))
(add-hook mode (lambda () (display-line-numbers-mode 0))))

Miscellaneous Minor Modes

These are some useful minor modes that I tend to use.

(save-place-mode) ;; Save location
(global-visual-line-mode) ;; Wrap lines
(global-auto-revert-mode) ;; Revert buffers

Fonts

Set font and fringe background color:

(setq text-scale-mode-step 1.1)

(set-face-attribute 'default nil :family "Iosevka" :weight 'regular :height 140)
(set-face-attribute 'fixed-pitch nil :font "Iosevka" :weight 'regular :height 1.0)
(set-face-attribute 'variable-pitch nil :font "Times New Roman" :height 140)

Indentations

Configuring indentation.

(setq-default indent-tabs-mode nil
    tab-width 2)
(setq indent-line-function 'insert-tab)

All The Icons

Fonts used by doom-modeline.

Prerequisites

Install the fonts first by running:

(all-the-icons-install-fonts)

Package Installation

Install the package using:

(use-package all-the-icons)

Evil Mode

Here we install and configure evil, since I cannot use the default Emacs keys. Evil is the only way I’ve managed to move to Emacs. The Vim key bindings are a lot better than the Emacs keybindings. Evil-collection is for miscellaneous minor modes, evil-org for org mode, and evil-leader adds a leader key.

Base

This is the main evil package, that allows you to use vim keybindings.

(use-package evil
  :init
  (setq evil-want-integration t)
  (setq evil-want-keybinding nil)
  :config
  (evil-mode 1))

Collection

This package adds Vim keybindings for miscellaneous minor modes, such as dired and mu4e.

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

Evil Org

For some reason evil-collection doesn’t include org bindings, so we install another package.

(use-package evil-org
  :diminish evil-org-mode
  :after org
  :config
  (add-hook 'org-mode-hook 'evil-org-mode)
  (add-hook 'evil-org-mode-hook
            (lambda () (evil-org-set-key-theme))))

(require 'evil-org-agenda)
(evil-org-agenda-set-keys)

Leader

This adds a leader key to Emacs, which is incredibly useful.

(use-package evil-leader
  :config
  (global-evil-leader-mode)
  (evil-leader/set-leader "<SPC>")
  (evil-leader/set-key
    ;; General
    ".f" 'consult-isearch
    ".q" 'delete-frame
    ".e" 'eval-region
    ".s" 'straight-use-package
    ;; Configs
    "ce" (lambda () (interactive) (find-file "~/.emacs.d/README.org"))
    ;; Undo
    "uv" 'undo-tree-visualize
    "uu" 'undo-tree-undo
    "ur" 'undo-tree-redo
    "uc" 'consult-yank-pop
    ;; Words
    "wt" 'mw-thesaurus-lookup-dwim
    "wd" 'dictionary-lookup-definition
    "we" 'emoji-insert
    ;; Files
    "fr" 'consult-recent-file
    "fb" 'consult-bookmark
    "ff" 'find-file
    ;; Bufffers
    "bv" 'split-window-right
    "bh" 'split-window-below
    "bd" 'kill-current-buffer
    "bb" 'consult-buffer
    "bx" 'switch-to-scratch
    ;; Projectile
    "pa" 'projectile-add-known-project
    "pf" 'consult-projectile
    "pp" 'projectile-switch-project
    "pg" 'projectile-grep
    "pm" 'projectile-commander
    "pc" 'projectile-compile-project
    ;; Org Mode
    "oc" 'org-edit-special
    "ol" 'org-latex-preview
    "ot" 'org-ctrl-c-ctrl-c
    "oi" 'org-toggle-inline-images
    "oa" 'org-agenda
    "os" 'org-schedule
    ; Export
    "oep" 'org-latex-export-to-pdf
    "oeh" 'org-html-export-to-html
    "oem" 'org-man-export-to-man
    "oeu" 'org-publish-project
    ; Babel
    "obs" 'org-babel-execute-src-block
    "obb" 'org-babel-execute-buffer
    "obl" 'org-babel-load-file
    ;; Help
    "hh" 'help
    "hk" 'describe-key
    "hv" 'describe-variable
    "hf" 'describe-function
    "hs" 'describe-symbol
    "hm" 'describe-mode
    ;; Magit
    "gi" 'magit-init
    "gc" 'magit-commit
    "gp" 'magit-push
    "gC" 'magit-clone
    "gs" 'magit-status))

Additional Keybindings

Here I bind some extra keybindings for evil mode.

(define-key evil-normal-state-map (kbd "M-s") 'save-buffer)
(define-key evil-normal-state-map (kbd "M-q") 'delete-window)
(define-key evil-normal-state-map (kbd "M-w") 'kill-current-buffer)

(define-key evil-normal-state-map (kbd "<C-tab>") 'consult-buffer)

(define-key evil-normal-state-map (kbd "C-h") 'evil-window-left)
(define-key evil-normal-state-map (kbd "C-j") 'evil-window-down)
(define-key evil-normal-state-map (kbd "C-k") 'evil-window-up)
(define-key evil-normal-state-map (kbd "C-l") 'evil-window-right)
(define-key evil-normal-state-map (kbd "M-j") 'evil-scroll-down)
(define-key evil-normal-state-map (kbd "M-k") 'evil-scroll-up)

(define-key evil-normal-state-map "u" 'undo-tree-undo)
(define-key evil-normal-state-map (kbd "C-r") 'undo-tree-redo)

(define-key evil-normal-state-map (kbd "M-t") 'neotree-toggle)
(define-key evil-normal-state-map (kbd "M-m") 'minimap-mode)
(define-key evil-normal-state-map (kbd "<C-return>") 'shr-browse-url)
(define-key key-translation-map (kbd "ESC") (kbd "C-g"))

(define-key evil-normal-state-map (kbd "C-=") 'text-scale-increase)
(define-key evil-normal-state-map (kbd "C--") 'text-scale-decrease)
(define-key evil-normal-state-map (kbd "C-0") 'text-scale-adjust)

(define-key evil-normal-state-map (kbd "<remap> <evil-next-line>") 'evil-next-visual-line)
(define-key evil-normal-state-map (kbd "<remap> <evil-previous-line>") 'evil-previous-visual-line)
(define-key evil-motion-state-map (kbd "<remap> <evil-next-line>") 'evil-next-visual-line)
(define-key evil-motion-state-map (kbd "<remap> <evil-previous-line>") 'evil-previous-visual-line)

(defun my/c-c ()
  (interactive)
  (setq unread-command-events (listify-key-sequence (kbd "C-c"))))

(defun my/c-k ()
  (interactive)
  (setq unread-command-events (listify-key-sequence (kbd "C-k"))))

(evil-define-key 'normal global-map (kbd ",c") 'my/c-c)
(evil-define-key 'normal global-map (kbd ",x") 'my/c-k)

Miscellaneous Settings

Cursor Shapes

Set the cursor shape for different evil states.

(set-default 'evil-normal-state-cursor 'box)
(set-default 'evil-insert-state-cursor 'bar)
(set-default 'evil-visual-state-cursor 'hbar)
(set-default 'evil-motion-state-cursor 'box)
(set-default 'evil-replace-state-cursor 'box)
(set-default 'evil-operator-state-cursor 'hbar)
(set-cursor-color "#B37AAE")
(setq-default cursor-type 'bar)

Small Additions

We want some Emacs in evil, so we change a few settings here.

(setq evil-cross-lines t
      evil-move-beyond-eol t
      evil-symbol-word-search t
      evil-want-Y-yank-to-eol t
      evil-cross-lines t)

Additional Packages

Which Key

We install which-key in case we ever forget any keybinds.

(use-package which-key
  :config (which-key-mode)
  (which-key-setup-side-window-bottom)
  (setq which-key-idle-delay 0.1))

M-x Completion

Vertico helps with better completion and to replace the default M-x. Consult adds a few things. Orderless adds fuzzy findings, marginalia adds stuff to your minibuffer.

(use-package consult)

(use-package vertico
  :ensure t
  :bind (:map vertico-map
         ("C-j" . vertico-next)
         ("C-k" . vertico-previous))
  :init
  (vertico-mode)
  :config
  (setq vertico-cycle t))

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

(use-package marginalia
  :after vertico
  :ensure t
  :custom
  (maarginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
  :init
  (marginalia-mode))

Neotree

Neotree is a cool file tree, so we install it. Although I usually use dired, neotree can be useful if you need a tree layout.

(use-package neotree)
(setq neo-theme (if (display-graphic-p) 'icons 'arrow))
(add-hook 'neotree-mode-hook
         (lambda ()
           (define-key evil-normal-state-local-map (kbd "SPC") 'neotree-quick-look)
           (define-key evil-normal-state-local-map (kbd "RET") 'neotree-enter)
           (define-key evil-normal-state-local-map (kbd "g") 'neotree-refresh)
           (define-key evil-normal-state-local-map (kbd "n") 'neotree-next-line)
           (define-key evil-normal-state-local-map (kbd "p") 'neotree-previous-line)
           (define-key evil-normal-state-local-map (kbd "A") 'neotree-stretch-toggle)
           (define-key evil-normal-state-local-map (kbd "H") 'neotree-hidden-file-toggle)))
(setq neo-window-fixed-size nil)

'(neo-dir-link-face ((t (:foreground "deep sky blue" :slant normal :weight bold :height 100 :family "Fira Code"))))
'(neo-file-link-face ((t (:foreground "White" :weight normal :height 120 :family "Fira Code"))))

Magit

Magit is the best git client, and it is a must. Less typing, less time spent using git, and more coding.

(use-package magit
  :defer t)

Parentheses

Smart parentheses

Most code editors automatically match parentheses, but Emacs doesn’t do this, so we install a package.

(use-package smartparens
  :config (smartparens-global-mode)
  (show-smartparens-mode))

Rainbow parentheses

Most editors also automatically color matching parentheses, but we need to install a package for this to happen.

(use-package rainbow-delimiters
  :config
  (add-hook 'prog-mode-hook #'rainbow-delimiters-mode))

Modeline

The default mode line is ugly, so this package replaces it with one that looks like the Doom mode line.

(setq display-time-default-load-average nil)

(line-number-mode)
(column-number-mode)
(display-time-mode -1)
(size-indication-mode -1)

(use-package doom-modeline
  :init (doom-modeline-mode)
  :config
  (setq doom-modeline-buffer-file-name-style 'file-name
        doom-modeline-height 30
        doom-modeline-enable-word-count t
        doom-modeline-buffer-encoding nil
        doom-modeline-icon t
        doom-modeline-modal-icon nil
        doom-modeline-major-mode-icon t
        doom-modeline-major-mode-color-icon t
        doom-modeline-bar-width 3))

(custom-set-faces
 '(mode-line ((t (:family "Iosevka" :height 110)))))

(use-package hide-mode-line
  :hook
  (special-mode . hide-mode-line-mode)
  (term-mode . hide-mode-line-mode)
  (neotree-mode . hide-mode-line-mode))

Undo Tree

We want to visualize the undo history better, so we install the undo-tree package. Oh and we don’t want to save the history.

(use-package undo-tree
  :config
  (global-undo-tree-mode)
  (setq undo-tree-auto-save-history nil))

Formatter

Let’s install a formatter to format our horrible code.

(use-package format-all
  :init (format-all-mode))

LSP

I use Emacs for coding as well, so we’re going to configure lsp-mode.

(use-package lsp-mode
  :init
  :hook (prog-mode . lsp-mode)
         ; (lua-mode . lsp)
         ; (python-mode . lsp)
         ; (sh-mode . lsp)
         ; (lisp-mode . lsp)
         ; (css-mode . lsp)
         ; (html-mode . lsp)
         ; (json-mode . lsp)
         ; (markdown-mode . lsp)
         ; (latex-mode . lsp)
         ; (go-mode . lsp)
         ; (text-mode . lsp)
         ; (org-mode . lsp-mode))
  :commands lsp
  :config
  (setq lsp-enable-symbol-highlighting nil
      lsp-enable-which-key-integration t
      lsp-ui-doc-enable t
      lsp-lens-enable nil
      lsp-headerline-breadcrumb-enable nil
      lsp-ui-sideline-enable nil
      lsp-ui-sideline-enable t
      lsp-modeline-code-actions-enable t
      lsp-ui-sideline-enable t
      lsp-ui-doc-border nil
      lsp-eldoc-enable-hover t
      lsp-log-io nil
      lsp-enable-file-watchers nil))

; (use-package lsp-grammarly)

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

(use-package lsp-treemacs
  :after lsp)

(setq lsp-enable-symbol-highlighting nil)

Company

Company is used for completions.

(use-package company
  :after lsp-mode
  :hook (lsp-mode . company-mode)
  :bind (:map company-active-map
              ("<tab>" . company-complete-selection))
        (:map lsp-mode-map
              ("<tab>" . company-indent-or-complete-common))
  :custom
  (company-minimum-prefix-length 1)
  (company-idle-delay 0.0))

(use-package company-box
  :hook (company-mode . company-box-mode))

Flycheck

Syntax checking for code.

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

Projectile

Here, we install and configure projectile, which is a project interaction library.

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

Org Mode

Org Download

Drag-and-drop images directly into Emacs!

(use-package org-download)

Org Indent

Indent the contents of an Org document.

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

Pretty Entities

Renders a handful of LaTeX expressions.

; (add-hook 'org-mode-hook 'org-toggle-pretty-entities)

Org Bullets

Customize the face of the bullets.

(use-package org-bullets
  :ensure t
  :init
  (setq org-bullets-bullet-list
        '(""))
  :config
  (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))

Org Ellipses

Change the character for the ellipses.

(setq org-ellipsis "")

Org TOC

We like table of contents, right?

(use-package toc-org)

SVG Tag Mode

(use-package svg-tag-mode
  :init
  (defconst date-re "[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}")
  (defconst time-re "[0-9]\\{2\\}:[0-9]\\{2\\}")
  (defconst day-re "[A-Za-z]\\{3\\}")

  (defun svg-progress-percent (value)
    (svg-image (svg-lib-concat
                (svg-lib-progress-bar (/ (string-to-number value) 100.0)
                                  nil :margin 0 :stroke 2 :radius 3 :padding 2 :width 11)
                (svg-lib-tag (concat value "%")
                             nil :stroke 0 :margin 0)) :ascent 'center))

  (defun svg-progress-count (value)
    (let* ((seq (mapcar #'string-to-number (split-string value "/")))
           (count (float (car seq)))
           (total (float (cadr seq))))
    (svg-image (svg-lib-concat
                (svg-lib-progress-bar (/ count total) nil
                                      :margin 0 :stroke 2 :radius 3 :padding 2 :width 11)
                (svg-lib-tag value nil
                             :stroke 0 :margin 0)) :ascent 'center)))

  (setq svg-tag-tags
    `(
       ;; Org tags

       ; (":\\([A-Za-z0-9]+\\)" . ((lambda (tag) (svg-tag-make tag))))
       ; (":\\([A-Za-z0-9]+[ \-]\\)" . ((lambda (tag) tag)))

       ;; Task priority

       ("\\[#[A-Z]\\]" . ( (lambda (tag)
                             (svg-tag-make tag :face 'org-priority 
                                           :beg 2 :end -1 :margin 0))))

       ;; Progress

       ("\\(\\[[0-9]\\{1,3\\}%\\]\\)" . ((lambda (tag)
                                           (svg-progress-percent (substring tag 1 -2)))))
       ("\\(\\[[0-9]+/[0-9]+\\]\\)" . ((lambda (tag)
                                         (svg-progress-count (substring tag 1 -1)))))

       ;; TODO / DONE
       ("TODO" . ((lambda (tag) (svg-tag-make "TODO" :face 'org-todo :inverse t :margin 0))))
       ("DONE" . ((lambda (tag) (svg-tag-make "DONE" :face 'org-done :margin 0))))
       ("IN PROGRESS" . ((lambda (tag) (svg-tag-make "IN PROGRESS" :face 'org-done :margin 0))))
       ("CANCELLED" . ((lambda (tag) (svg-tag-make "CANCELLED" :face 'org-done :margin 0))))

       ;; Citation of the form [cite:@Knuth:1984] 

       ("\\(\\[cite:@[A-Za-z]+:\\)" . ((lambda (tag)
                                         (svg-tag-make tag
                                                       :inverse t
                                                       :beg 7 :end -1
                                                       :crop-right t))))
       ("\\[cite:@[A-Za-z]+:\\([0-9]+\\]\\)" . ((lambda (tag)
                                               (svg-tag-make tag
                                                             :end -1
                                                             :crop-left t))))

       ;; Active date (without day name, with or without time)

       (,(format "\\(<%s>\\)" date-re) .
        ((lambda (tag)
           (svg-tag-make tag :beg 1 :end -1 :margin 0))))
       (,(format "\\(<%s *\\)%s>" date-re time-re) .
        ((lambda (tag)
           (svg-tag-make tag :beg 1 :inverse nil :crop-right t :margin 0))))
       (,(format "<%s *\\(%s>\\)" date-re time-re) .
        ((lambda (tag)
           (svg-tag-make tag :end -1 :inverse t :crop-left t :margin 0))))

       ;; Inactive date (without day name, with or without time)

        (,(format "\\(\\[%s\\]\\)" date-re) .
         ((lambda (tag)
            (svg-tag-make tag :beg 1 :end -1 :margin 0 :face 'org-date))))
        (,(format "\\(\\[%s *\\)%s\\]" date-re time-re) .
         ((lambda (tag)
            (svg-tag-make tag :beg 1 :inverse nil :crop-right t :margin 0 :face 'org-date))))
        (,(format "\\[%s *\\(%s\\]\\)" date-re time-re) .
         ((lambda (tag)
            (svg-tag-make tag :end -1 :inverse t :crop-left t :margin 0 :face 'org-date))))))
    :hook org-mode)

Keywords

Let’s add our own custom keywords and highlight them.

(setq org-todo-keywords
     '((sequence "TODO" "IN PROGRESS" "CANCELLED" "DONE")))

Functions

Compilation

A keybind for compilation.

(global-set-key (kbd "S-<f9>") 'compile)
(global-set-key (kbd "<f9>") 'recompile)