#+TITLE: My Emacs Configuration #+AUTHOR: Amneesh Singh #+PROPERTY: header-args :emacs-lisp :tangle yes * Settings ** Setting the default face #+begin_src emacs-lisp ; -*- lexical-binding: t; -*- (set-frame-font "Fira Code 13" nil t) (add-to-list 'default-frame-alist '(font . "Fira Code-13")) #+end_src ** Some mode settings based on personal preferences #+begin_src emacs-lisp (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) #+end_src ** Setting some variables #+begin_src emacs-lisp (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) #+end_src ** Emacs startup hook #+begin_src emacs-lisp (add-hook 'emacs-startup-hook (lambda () (delete-other-windows)) t) #+end_src * Packages ** Add Melpa to package archives #+begin_src emacs-lisp (require 'package) (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/")) (package-initialize) (require 'use-package) #+end_src *** Profiling #+begin_src emacs-lisp (use-package benchmark-init :config ;; To disable collection of benchmark data after init is done. :init (benchmark-init/deactivate)) #+end_src ** Visual packages *** Add solaire mode #+begin_src emacs-lisp (use-package solaire-mode :config (solaire-mode)) #+end_src *** Set theme #+begin_src emacs-lisp (use-package catppuccin-theme :config (load-theme 'catppuccin t) :custom (dark-theme t)) #+end_src ** Configure Selectrum Enable selectrum #+begin_src emacs-lisp (use-package selectrum :defer t :config (selectrum-mode +1)) #+end_src Add selectrum-prescient #+begin_src emacs-lisp (use-package selectrum-prescient :config (selectrum-prescient-mode +1) (prescient-persist-mode +1)) #+end_src #+begin_src emacs-lisp (use-package orderless :after selectrum :config (setq completion-styles '(orderless basic)) (savehist-mode) (setq orderless-skip-highlighting (lambda () selectrum-is-active) selectrum-highlight-candidates-function #'orderless-highlight-matches)) #+end_src ** Evil *** Configure evil mode #+begin_src emacs-lisp (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)) #+end_src *** Configure undo tree To undo and redo easily like vi #+begin_src emacs-lisp (use-package undo-tree :init (setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo"))) :config (global-undo-tree-mode 1)) #+end_src *** Miscellaneous evil related packages #+begin_src emacs-lisp (use-package evil-terminal-cursor-changer :if (not (display-graphic-p)) :config (evil-terminal-cursor-changer-activate)) (use-package evil-anzu :after evil) #+end_src ** Treemacs *** Configure treemacs #+begin_src emacs-lisp (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) #+end_src ** LSP *** Configure lsp-mode #+begin_src emacs-lisp (use-package lsp-mode :defer t :commands lsp) #+end_src *** Configure lsp-ui #+begin_src emacs-lisp (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)) #+end_src *** Configure flycheck #+begin_src emacs-lisp (use-package flycheck :defer t) #+end_src *** Configure dap-mode #+begin_src emacs-lisp (use-package dap-mode :defer t :hook ((lsp-mode . dap-mode) (lsp-mode . dap-ui-mode))) #+end_src ** Company *** Configure company For autocomplete #+begin_src emacs-lisp (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)) #+end_src *** Configure company-quickhelp #+begin_src emacs-lisp (use-package company-quickhelp :hook (company-mode . company-quickhelp-mode)) #+end_src ** Treesitter #+begin_src emacs-lisp (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)) #+end_src ** Direnv #+begin_src emacs-lisp (use-package direnv :config (direnv-mode)) #+end_src ** Languages #+begin_src emacs-lisp (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\\'") #+end_src ** Magit #+begin_src emacs-lisp (use-package magit :defer t) #+end_src ** VTerm *** Configure vterm #+begin_src emacs-lisp (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)))) #+end_src ** Centaur Tabs Do not use centaur tabs for now #+begin_src emacs-lisp :tangle no (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))) #+end_src ** Misc packages #+begin_src emacs-lisp (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) #+end_src ** Org ** Add org-mode #+begin_src emacs-lisp (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)) #+end_src ** Add org-bullets #+begin_src emacs-lisp (use-package org-bullets :defer t :hook ((org-mode . org-bullets-mode))) #+end_src ** Babel and exports #+begin_src emacs-lisp (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))) #+end_src * Mode specific hooks #+begin_src emacs-lisp (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) #+end_src * Random eye candy stuff * Custom mode line switched to doom modeline after using my own modeline for a while #+begin_src emacs-lisp (use-package doom-modeline :init (doom-modeline-mode 1)) #+end_src * Pop-up terminal Stolen from [[https://www.reddit.com/r/emacs/comments/ft84xy/run_shell_command_in_new_vterm/][this]] reddit post #+begin_src emacs-lisp (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))) #+end_src Compilation shortcuts for standalone files #+begin_src emacs-lisp (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))))) #+end_src * Custom Functions #+begin_src emacs-lisp (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))) #+end_src * Keybinds ** General *** Colemak translations not using this anymore #+begin_src emacs-lisp :tangle no (use-package evil-colemak-basics :init (setq evil-colemak-basics-layout-mod 'mod-dh) :config (global-evil-colemak-basics-mode)) #+end_src *** Misc binds #+begin_src emacs-lisp (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) #+end_src *** Pop-up terminal specific keybinds #+begin_src emacs-lisp (with-eval-after-load 'vterm-toggle (general-define-key :keymaps '(global override vterm-mode-map) :states evil-states "" (lambda () (interactive) (vterm t)) "C-S-t" 'vterm-toggle-cd "C-t" 'vterm-toggle "" 'vterm-toggle "" (lambda () (interactive) (run-in-vterm (candrun)))) (general-define-key :keymaps 'vterm-mode-map "" 'vterm-toggle-forward "" 'vterm-toggle-backward))) #+end_src