Files
dotfiles/home/common/emacs/config

My Emacs Configuration

Settings

Setting the default face

 ; -*- lexical-binding: t; -*-
(set-frame-font "Fira Code 13" nil t)
(add-to-list 'default-frame-alist '(font . "Fira Code-13"))

Some mode settings based on personal preferences

(add-hook 'prog-mode-hook #'hl-line-mode)
(add-hook 'text-mode-hook #'hl-line-mode)
(scroll-bar-mode 0)
(tool-bar-mode 0)
(menu-bar-mode 0)
(fringe-mode 0)
(global-display-line-numbers-mode 1)
(xterm-mouse-mode 1)
(setq ring-bell-function 'ignore
      gc-cons-threshold most-positive-fixnum
      initial-major-mode 'fundamental-mode)

Setting some variables

(setq initial-major-mode 'emacs-lisp-mode
      frame-resize-pixelwise t
      auto-window-vscroll nil
      scroll-step 1
      display-line-numbers-type 'relative
      confirm-kill-processes nil
      inhibit-startup-screen t)
(setq-default tab-width 2
              indent-tabs-mode nil)

Emacs startup hook

(add-hook 'emacs-startup-hook
          (lambda () (delete-other-windows)) t)

Packages

Add Melpa to package archives

(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/"))
(package-initialize)
(require 'use-package)

Profiling

(use-package benchmark-init
  :config
  ;; To disable collection of benchmark data after init is done.
  :init (benchmark-init/deactivate))

Visual packages

Add solaire mode

(use-package solaire-mode
  :config
  (solaire-mode))

Set theme

(use-package catppuccin-theme
  :config
  (load-theme 'catppuccin t)
  :custom
  (dark-theme t))

Minibuffer

Enable vertico

(use-package vertico
  :init
  (vertico-mode)
  :bind (:map vertico-map
              ("C-j" . vertico-next)
              ("C-k" . vertico-previous)))

Marginalia for description

(use-package marginalia
  :after vertico
  :config
  (marginalia-mode 1))

Orderless

(use-package orderless
  :after vertico
  :config
  (setq completion-styles '(orderless basic)))

Consult

(use-package consult
  :bind (("M-s M-g" . consult-grep)
         ("M-s M-f" . consult-find)
         ("M-s M-b" . consult-buffer)))

Evil

Configure evil mode

(defun my/evil-shift-right ()
  (interactive)
  (evil-shift-right evil-visual-beginning evil-visual-end)
  (evil-normal-state)
  (evil-visual-restore))

(defun my/evil-shift-left ()
  (interactive)
  (evil-shift-left evil-visual-beginning evil-visual-end)
  (evil-normal-state)
  (evil-visual-restore))

(use-package evil
  :init
  (setq-default evil-shift-width 2)
  :config
  (evil-set-initial-state 'vterm-mode 'insert)
  (evil-set-undo-system 'undo-tree)
  (evil-define-key 'visual global-map (kbd ">") 'my/evil-shift-right)
  (evil-define-key 'visual global-map (kbd "<") 'my/evil-shift-left)
  (evil-mode 1))

Evil related packages

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

(use-package evil-terminal-cursor-changer
  :after evil
  :if (not (display-graphic-p))
  :config
  (evil-terminal-cursor-changer-activate))
(use-package evil-anzu :after evil)

Configure undo tree

To undo and redo easily like vi

(use-package undo-tree
  :init
  (setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo")))
  :config
  (global-undo-tree-mode 1))

Treemacs

Configure treemacs

(use-package treemacs
  :defer t
  :config
  (treemacs-project-follow-mode))

(use-package treemacs-evil :after treemacs)
(use-package treemacs-projectile :after treemacs)
(use-package treemacs-all-the-icons :after treemacs)

LSP

Configure lsp-mode

(use-package lsp-mode
  :defer t
  :commands lsp)

Configure lsp-ui

(use-package lsp-ui
  :defer t
  :init
  (setq lsp-ui-doc-delay 1.0
        lsp-ui-doc-show-with-mouse t
        pgtk-wait-for-event-timeout nil
        lsp-ui-doc-show-with-cursor t)
  :config
  (lsp-ui-peek-enable 1)
  (lsp-ui-doc-enable 1)
  :hook (lsp-mode . lsp-ui-mode))

Configure flycheck

(use-package flycheck
  :defer t)

Configure dap-mode

(use-package dap-mode
  :defer t
  :hook ((lsp-mode . dap-mode)
         (lsp-mode . dap-ui-mode)))

Company

Configure company

For autocomplete

(use-package company
  :after lsp-mode
  :config
  (add-to-list 'company-backends 'company-dabbrev)
  (setq company-backends (append '(company-files) (remove 'company-files company-backends)))
  :hook (after-init . global-company-mode))

Configure company-quickhelp

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

Treesitter

(use-package tree-sitter-langs :defer t)
(use-package tree-sitter
  :after tree-sitter-langs
  :defer t
  :config
  (global-tree-sitter-mode)
  :init
  (add-to-list 'tree-sitter-major-mode-language-alist '(fundamental-mode . bash))
  (add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode))

Direnv

(use-package direnv
 :config
 (direnv-mode))

Languages

(use-package lsp-haskell
  :mode "\\.hs\\'")
(use-package lsp-latex
  :mode "\\.tex\\'")
(use-package rustic
  :mode "\\.rs\\'")
(use-package typescript-mode
  :mode ("\\.ts\\'" "\\.tsx\\'"))
(use-package wgsl-mode
  :mode "\\.wgsl\\'")
(use-package nix-mode
  :mode "\\.nix\\'")
(use-package hcl-mode
  :mode
  "\\.hcl\\'"
  "\\.nomad\\'")
(use-package go-mode
  :mode "\\.go\\'")

Magit

(use-package magit :defer t)

VTerm

Configure vterm

(use-package vterm
  :config
  (evil-define-key 'normal vterm-mode-map (kbd "p") 'vterm-yank)
  (evil-define-key 'insert vterm-mode-map (kbd "C-y") 'vterm-yank)
  (setq vterm-timer-delay 0.005))

(use-package vterm-toggle
  :after vterm
  :config
  (setq vterm-toggle-fullscreen-p nil)
  (add-to-list 'display-buffer-alist
               '((lambda (buffer-or-name _)
                      (let ((buffer (get-buffer buffer-or-name)))
                        (with-current-buffer buffer
                          (or (equal major-mode 'vterm-mode)
                              (string-prefix-p vterm-buffer-name (buffer-name buffer))))))
               (display-buffer-reuse-window display-buffer-in-side-window)
               (side . bottom)
               (reusable-frames . visible)
               (window-height . 0.4))))

Centaur Tabs

Do not use centaur tabs for now

(use-package centaur-tabs
  :defer t
  :custom
  (centaur-tabs-style "rounded")
	(centaur-tabs-height 18)
	(centaur-tabs-set-modified-marker t)
	(centaur-tabs-set-icons t)
  :config
  (centaur-tabs-mode t)
  (centaur-tabs-group-by-projectile-project)
  (set-face-attribute 'tab-line nil :inherit 'centaur-tabs-unselected)
  (centaur-tabs-headline-match)
  :bind
  (:map evil-normal-state-map
    ("M-," . centaur-tabs-forward)
    ("M-." . centaur-tabs-backward))
  (:map evil-motion-state-map
    ("M-," . centaur-tabs-forward)
    ("M-." . centaur-tabs-backward)))

Misc packages

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

(use-package elcord :defer t)

(use-package projectile
  :defer t
  :config
  (define-key projectile-mode-map (kbd "C-x p") 'projectile-command-map)
  (projectile-mode +1))

(use-package rainbow-mode :defer t)

(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode))

(use-package flex-autopair)

Org

Add org-mode

(use-package org
  :defer t
  :after evil
  :config
  (define-key org-mode-map (kbd "RET") 'org-return-and-maybe-indent)
  (evil-define-key 'normal org-mode-map (kbd "TAB") 'org-cycle)
  :custom
  (evil-want-C-i-jump nil)
  (org-adapt-indentation t)
  (org-src-fontify-natively t)
  (org-src-strip-leading-and-trailing-blank-lines t)
  (org-src-preserve-indentation t)
  (org-src-tab-acts-natively t))

Add org-bullets

 (use-package org-bullets
  :defer t
  :hook ((org-mode . org-bullets-mode)))

Babel and exports

(use-package htmlize :defer t)

(setq org-latex-listings 'minted
      org-latex-packages-alist '(("" "minted"))
      org-latex-pdf-process
      '("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
        "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
        "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"))

(setq org-src-fontify-natively t)
(setq org-confirm-babel-evaluate nil)

(org-babel-do-load-languages
 'org-babel-load-languages
 '((python . t)
   (C . t)
   (sql . t)
   (latex . t)))

Mode specific hooks

(add-hook 'c-mode-hook 'lsp)
(add-hook 'c++-mode-hook 'lsp)
(add-hook 'haskell-mode-hook #'lsp)
(add-hook 'haskell-literate-mode-hook #'lsp)

Random eye candy stuff

Custom mode line

switched to doom modeline after using my own modeline for a while

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

Pop-up terminal

Stolen from this reddit post

(defun run-in-vterm-kill (process event)
  "A process sentinel. Kills PROCESS's buffer if it is live."
  (let ((b (process-buffer process)))
    (and (buffer-live-p b)
         (kill-buffer b))))

(defun run-in-vterm (command)
  (interactive
   (list
    (let* ((f (cond (buffer-file-name)
                    ((eq major-mode 'dired-mode)
                     (dired-get-filename nil t))))
           (filename (concat " " (shell-quote-argument (and f (file-relative-name f))))))
      (read-shell-command "Terminal command: "
                          (cons filename 0)
                          (cons 'shell-command-history 1)
                          (list filename)))))
  (with-current-buffer (vterm-toggle)
    (set-process-sentinel vterm--process #'run-in-vterm-kill)
    (vterm-send-string (concat command))
    (vterm-send-return)))

Compilation shortcuts for standalone files

(defun candrun ()
  (let ((full buffer-file-name)
        (file (file-name-sans-extension buffer-file-name)))
    (pcase (file-name-extension full)
           ("c" (concat "gcc " full " -lm -pthread -o " file " && " file " && rm " file))
           ("java" (concat "java " full))
           ("py" (concat "python " full))
           ("cpp" (concat "g++ " full " -o " file " && " file " && rm " file))
           ("cc" (concat "g++ " full " -o " file " && " file " && rm " file))
           ("hs" (concat "runhaskell " full))
           ("sh" (concat "sh " full))
           ("js" (concat "node " full))
           ("ts" (concat "tsc " full " && node " file ".js && rm " file ".js" ))
           ("rs" (concat "rustc " full " -o " file " && " file " && rm " file)))))

Custom Functions

(defun detach-process ()
  "Run processes but detached from the parent"
  (interactive)
  (let ((command (read-string "Enter command:")))
    (call-process-shell-command (concat command " &") nil 0)))

Keybinds

General

Colemak translations

not using this anymore

(use-package evil-colemak-basics
  :init
  (setq evil-colemak-basics-layout-mod 'mod-dh)
  :config
  (global-evil-colemak-basics-mode))

Misc binds

(use-package general
  :ensure t)

(setq evil-states
  '(visual normal motion))

(with-eval-after-load 'general
  (general-define-key
    :states evil-states
    "M-c" 'comment-line
    "C-c M-c" 'comment-box)

  (general-define-key
    :states '(normal insert)
    "M-C-f" 'lsp-format-buffer
    "C-S-v" 'yank)

  (general-define-key
    :keymaps '(global override vterm-mode-map)
    :states evil-states
    "M-o" 'treemacs
    "M-s-v" 'split-window-vertically
    "M-s-h" 'split-window-horizontally
    "M-h" 'windmove-left
    "M-j" 'windmove-down
    "M-k" 'windmove-up
    "M-l" 'windmove-right
    "M-C-h" 'shrink-window-horizontally
    "M-C-l" 'enlarge-window-horizontally
    "M-C-j" 'shrink-window
    "M-C-k" 'enlarge-window
    "C-q"  'delete-window
    "M-C-S-q"  'kill-buffer-and-window
    "M-w"  (lambda () (interactive) (kill-buffer (current-buffer)))
    "M-S-w"  'kill-window)

Pop-up terminal specific keybinds

  (with-eval-after-load 'vterm-toggle
    (general-define-key
      :keymaps '(global override vterm-mode-map)
      :states evil-states
      "<f4>"  (lambda () (interactive) (vterm t))
      "C-S-t" 'vterm-toggle-cd
      "C-t" 'vterm-toggle
      "<f1>" 'vterm-toggle
      "<f5>" (lambda () (interactive) (run-in-vterm (candrun))))
    (general-define-key
      :keymaps 'vterm-mode-map
      "<f3>" 'vterm-toggle-forward
      "<f2>" 'vterm-toggle-backward)))