Skip to content

madhavan-raja/emacs-config

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

93 Commits
 
 
 
 
 
 
 
 

Repository files navigation

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)

About

My Emacs configuration!

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published