#+TITLE: DT's GNU Emacs Config #+AUTHOR: Derek Taylor (DT) #+DESCRIPTION: DT's personal Emacs config. #+STARTUP: showeverything #+OPTIONS: toc:2 * TABLE OF CONTENTS :toc: - [[#important-programs-to-load-first][IMPORTANT PROGRAMS TO LOAD FIRST]] - [[#adding-the-scripts-directory-to-path][Adding the scripts directory to path]] - [[#sourcing-the-scripts][Sourcing the scripts]] - [[#all-the-icons][ALL THE ICONS]] - [[#backup][BACKUP]] - [[#company][COMPANY]] - [[#dashboard][DASHBOARD]] - [[#diminish][DIMINISH]] - [[#dired][DIRED]] - [[#evil][EVIL]] - [[#flycheck][FLYCHECK]] - [[#fonts][FONTS]] - [[#setting-the-font-face][Setting the Font Face]] - [[#zooming-inout][Zooming In/Out]] - [[#general-keybindings][GENERAL KEYBINDINGS]] - [[#graphical-user-interface-tweaks][GRAPHICAL USER INTERFACE TWEAKS]] - [[#disable-menubar-toolbars-and-scrollbars][Disable Menubar, Toolbars and Scrollbars]] - [[#display-line-numbers-and-truncated-lines][Display Line Numbers and Truncated Lines]] - [[#ivy-counsel][IVY (COUNSEL)]] - [[#language-support][LANGUAGE SUPPORT]] - [[#modeline][MODELINE]] - [[#neotree][NEOTREE]] - [[#org-mode][ORG MODE]] - [[#enabling-table-of-contents][Enabling Table of Contents]] - [[#enabling-org-bullets][Enabling Org Bullets]] - [[#disable-electric-indent][Disable Electric Indent]] - [[#diminish-org-indent-mode][Diminish Org Indent Mode]] - [[#org-level-headers][Org Level Headers]] - [[#source-code-block-tag-expansion][Source Code Block Tag Expansion]] - [[#projectile][PROJECTILE]] - [[#rainbow-mode][RAINBOW MODE]] - [[#shells-and-terminals][SHELLS AND TERMINALS]] - [[#eshell][Eshell]] - [[#vterm][Vterm]] - [[#vterm-toggle][Vterm-Toggle]] - [[#sudo-edit][SUDO EDIT]] - [[#theme][THEME]] - [[#transparency][TRANSPARENCY]] - [[#which-key][WHICH-KEY]] * IMPORTANT PROGRAMS TO LOAD FIRST To keep this =config.org= a reasonable length, I have moved a lot of code to individual scripts that will be sourced by this config. These scripts are found in "~/.config/emacs/scripts" and do not contain any code that most people are likely to need to edit. ** Adding the scripts directory to path #+begin_src emacs-lisp (add-to-list 'load-path "~/.config/emacs/scripts/") #+end_src ** Sourcing the scripts #+begin_src emacs-lisp (require 'elpaca-setup) ;; The Elpaca Package Manager (require 'buffer-move) ;; Buffer-move for better window management (require 'app-launchers) ;; Use emacs as a run launcher like dmenu (experimental) #+end_src * ALL THE ICONS This is an icon set that can be used with dashboard, dired, ibuffer and other Emacs programs. #+begin_src emacs-lisp (use-package all-the-icons :ensure t :if (display-graphic-p)) (use-package all-the-icons-dired :hook (dired-mode . (lambda () (all-the-icons-dired-mode t)))) #+end_src * BACKUP By default, Emacs creates automatic backups of files in their original directories, such "file.el" and the backup "file.el~". This leads to a lot of clutter, so let's tell Emacs to put all backups that it creates in the =TRASH= directory. #+begin_src emacs-lisp (setq backup-directory-alist '((".*" . "~/.Trash"))) #+end_src * COMPANY [[https://company-mode.github.io/][Company]] is a text completion framework for Emacs. The name stands for "complete anything". Completion will start automatically after you type a few letters. Use M-n and M-p to select, to complete or to complete the common part. #+begin_src emacs-lisp (use-package company :defer 2 :diminish :custom (company-begin-commands '(self-insert-command)) (company-idle-delay .1) (company-minimum-prefix-length 2) (company-show-numbers t) (company-tooltip-align-annotations 't) (global-company-mode t)) (use-package company-box :after company :diminish :hook (company-mode . company-box-mode)) #+end_src * DASHBOARD Emacs Dashboard is an extensible startup screen showing you recent files, bookmarks, agenda items and an Emacs banner. #+begin_src emacs-lisp (use-package dashboard :ensure t :init (setq initial-buffer-choice 'dashboard-open) (setq dashboard-set-heading-icons t) (setq dashboard-set-file-icons t) (setq dashboard-banner-logo-title "Emacs Is More Than A Text Editor!") ;;(setq dashboard-startup-banner 'logo) ;; use standard emacs logo as banner (setq dashboard-startup-banner "/home/dt/.config/emacs/images/dtmacs-logo.png") ;; use custom image as banner (setq dashboard-center-content nil) ;; set to 't' for centered content (setq dashboard-items '((recents . 5) (agenda . 5 ) (bookmarks . 3) (projects . 3) (registers . 3))) :custom (dashboard-modify-heading-icons '((recents . "file-text") (bookmarks . "book"))) :config (dashboard-setup-startup-hook)) #+end_src * DIMINISH This package implements hiding or abbreviation of the modeline displays (lighters) of minor-modes. With this package installed, you can add ':diminish' to any use-package block to hide that particular mode in the modeline. #+begin_src emacs-lisp (use-package diminish) #+end_src * DIRED #+begin_src emacs-lisp (use-package dired-open :config (setq dired-open-extensions '(("gif" . "sxiv") ("jpg" . "sxiv") ("png" . "sxiv") ("mkv" . "mpv") ("mp4" . "mpv")))) (use-package peep-dired :after dired :hook (evil-normalize-keymaps . peep-dired-hook) :config (evil-define-key 'normal dired-mode-map (kbd "h") 'dired-up-directory) (evil-define-key 'normal dired-mode-map (kbd "l") 'dired-open-file) ; use dired-find-file instead if not using dired-open package (evil-define-key 'normal peep-dired-mode-map (kbd "j") 'peep-dired-next-file) (evil-define-key 'normal peep-dired-mode-map (kbd "k") 'peep-dired-prev-file) ) #+end_src * EVIL [[https://github.com/emacs-evil/evil][Evil]] is an extensible vi/vim layer for Emacs. Because...let's face it. The Vim keybindings are just plain better. #+begin_src emacs-lisp ;; Expands to: (elpaca evil (use-package evil :demand t)) (use-package evil :init ;; tweak evil's configuration before loading it (setq evil-want-integration t ;; This is optional since it's already set to t by default. evil-want-keybinding nil evil-vsplit-window-right t evil-split-window-below t evil-undo-system 'undo-redo) ;; Adds vim-like C-r redo functionality (evil-mode)) (use-package evil-collection :after evil :config (setq evil-collection-mode-list '(dashboard dired ibuffer)) (evil-collection-init)) (use-package evil-tutor) #+end_src * FLYCHECK Install =luacheck= from your Linux distro's repositories for flycheck to work correctly with lua files. Install =python-pylint= for flycheck to work with python files. Haskell works with flycheck as long as =haskell-ghc= or =haskell-stack-ghc= is installed. For more information on language support for flycheck, [[https://www.flycheck.org/en/latest/languages.html][read this]]. #+begin_src emacs-lisp (use-package flycheck :ensure t :defer t :diminish :init (global-flycheck-mode)) #+end_src * FONTS Defining the various fonts that Emacs will use. ** Setting the Font Face #+begin_src emacs-lisp (set-face-attribute 'default nil :font "JetBrains Mono" :height 110 :weight 'medium) (set-face-attribute 'variable-pitch nil :font "Ubuntu" :height 120 :weight 'medium) (set-face-attribute 'fixed-pitch nil :font "JetBrains Mono" :height 110 :weight 'medium) ;; Makes commented text and keywords italics. ;; This is working in emacsclient but not emacs. ;; Your font must have an italic face available. (set-face-attribute 'font-lock-comment-face nil :slant 'italic) (set-face-attribute 'font-lock-keyword-face nil :slant 'italic) ;; This sets the default font on all graphical frames created after restarting Emacs. ;; Does the same thing as 'set-face-attribute default' above, but emacsclient fonts ;; are not right unless I also add this method of setting the default font. (add-to-list 'default-frame-alist '(font . "JetBrains Mono-11")) ;; Uncomment the following line if line spacing needs adjusting. (setq-default line-spacing 0.12) #+end_src ** Zooming In/Out You can use the bindings CTRL plus =/- for zooming in/out. You can also use CTRL plus the mouse wheel for zooming in/out. #+begin_src emacs-lisp (global-set-key (kbd "C-=") 'text-scale-increase) (global-set-key (kbd "C--") 'text-scale-decrease) (global-set-key (kbd "") 'text-scale-increase) (global-set-key (kbd "") 'text-scale-decrease) #+end_src * GENERAL KEYBINDINGS #+begin_src emacs-lisp (use-package general :config (general-evil-setup) ;; set up 'SPC' as the global leader key (general-create-definer dt/leader-keys :states '(normal insert visual emacs) :keymaps 'override :prefix "SPC" ;; set leader :global-prefix "M-SPC") ;; access leader in insert mode (dt/leader-keys "SPC" '(counsel-M-x :wk "Counsel M-x") "." '(find-file :wk "Find file") "f c" '((lambda () (interactive) (find-file "~/.config/emacs/config.org")) :wk "Edit emacs config") "f r" '(counsel-recentf :wk "Find recent files") "TAB TAB" '(comment-line :wk "Comment lines")) (dt/leader-keys "b" '(:ignore t :wk "Bookmarks/Buffers") "b c" '(clone-indirect-buffer :wk "Create indirect buffer copy in a split") "b C" '(clone-indirect-buffer-other-window :wk "Clone indirect buffer in new window") "b d" '(bookmark-delete :wk "Delete bookmark") "b i" '(ibuffer :wk "Ibuffer") "b k" '(kill-this-buffer :wk "Kill this buffer") "b K" '(kill-some-buffers :wk "Kill multiple buffers") "b l" '(list-bookmarks :wk "List bookmarks") "b m" '(bookmark-set :wk "Set bookmark") "b n" '(next-buffer :wk "Next buffer") "b p" '(previous-buffer :wk "Previous buffer") "b r" '(revert-buffer :wk "Reload buffer") "b R" '(rename-buffer :wk "Rename buffer") "b s" '(basic-save-buffer :wk "Save buffer") "b S" '(save-some-buffers :wk "Save multiple buffers") "b w" '(bookmark-save :wk "Save current bookmarks to bookmark file")) (dt/leader-keys "d" '(:ignore t :wk "Dired") "d d" '(dired :wk "Open dired") "d j" '(dired-jump :wk "Dired jump to current") "d n" '(neotree-dir :wk "Open directory in neotree") "d p" '(peep-dired :wk "Peep-dired")) (dt/leader-keys "e" '(:ignore t :wk "Eshell/Evaluate") "e b" '(eval-buffer :wk "Evaluate elisp in buffer") "e d" '(eval-defun :wk "Evaluate defun containing or after point") "e e" '(eval-expression :wk "Evaluate and elisp expression") "e h" '(counsel-esh-history :which-key "Eshell history") "e l" '(eval-last-sexp :wk "Evaluate elisp expression before point") "e r" '(eval-region :wk "Evaluate elisp in region") "e s" '(eshell :which-key "Eshell")) (dt/leader-keys "h" '(:ignore t :wk "Help") "h a" '(counsel-apropos :wk "Apropos") "h b" '(describe-bindings :wk "Describe bindings") "h c" '(describe-char :wk "Describe character under cursor") "h d" '(:ignore t :wk "Emacs documentation") "h d a" '(about-emacs :wk "About Emacs") "h d d" '(view-emacs-debugging :wk "View Emacs debugging") "h d f" '(view-emacs-FAQ :wk "View Emacs FAQ") "h d m" '(info-emacs-manual :wk "The Emacs manual") "h d n" '(view-emacs-news :wk "View Emacs news") "h d o" '(describe-distribution :wk "How to obtain Emacs") "h d p" '(view-emacs-problems :wk "View Emacs problems") "h d t" '(view-emacs-todo :wk "View Emacs todo") "h d w" '(describe-no-warranty :wk "Describe no warranty") "h e" '(view-echo-area-messages :wk "View echo area messages") "h f" '(describe-function :wk "Describe function") "h F" '(describe-face :wk "Describe face") "h g" '(describe-gnu-project :wk "Describe GNU Project") "h i" '(info :wk "Info") "h I" '(describe-input-method :wk "Describe input method") "h k" '(describe-key :wk "Describe key") "h l" '(view-lossage :wk "Display recent keystrokes and the commands run") "h L" '(describe-language-environment :wk "Describe language environment") "h m" '(describe-mode :wk "Describe mode") "h r" '(:ignore t :wk "Reload") "h r r" '((lambda () (interactive) (load-file "~/.config/emacs/init.el") (ignore (elpaca-process-queues))) :wk "Reload emacs config") "h t" '(load-theme :wk "Load theme") "h v" '(describe-variable :wk "Describe variable") "h w" '(where-is :wk "Prints keybinding for command if set") "h x" '(describe-command :wk "Display full documentation for command")) (dt/leader-keys "m" '(:ignore t :wk "Org") "m a" '(org-agenda :wk "Org agenda") "m e" '(org-export-dispatch :wk "Org export dispatch") "m i" '(org-toggle-item :wk "Org toggle item") "m t" '(org-todo :wk "Org todo") "m B" '(org-babel-tangle :wk "Org babel tangle") "m T" '(org-todo-list :wk "Org todo list")) (dt/leader-keys "m b" '(:ignore t :wk "Tables") "m b -" '(org-table-insert-hline :wk "Insert hline in table")) (dt/leader-keys "m d" '(:ignore t :wk "Date/deadline") "m d t" '(org-time-stamp :wk "Org time stamp")) (dt/leader-keys "p" '(projectile-command-map :wk "Projectile")) (dt/leader-keys "t" '(:ignore t :wk "Toggle") "t e" '(eshell-toggle :wk "Toggle eshell") "t f" '(flycheck-mode :wk "Toggle flycheck") "t l" '(display-line-numbers-mode :wk "Toggle line numbers") "t n" '(neotree-toggle :wk "Toggle neotree file viewer") "t r" '(rainbow-mode :wk "Toggle rainbow mode") "t t" '(visual-line-mode :wk "Toggle truncated lines") "t v" '(vterm-toggle :wk "Toggle vterm")) (dt/leader-keys "w" '(:ignore t :wk "Windows") ;; Window splits "w c" '(evil-window-delete :wk "Close window") "w n" '(evil-window-new :wk "New window") "w s" '(evil-window-split :wk "Horizontal split window") "w v" '(evil-window-vsplit :wk "Vertical split window") ;; Window motions "w h" '(evil-window-left :wk "Window left") "w j" '(evil-window-down :wk "Window down") "w k" '(evil-window-up :wk "Window up") "w l" '(evil-window-right :wk "Window right") "w w" '(evil-window-next :wk "Goto next window") ;; Move Windows "w H" '(buf-move-left :wk "Buffer move left") "w J" '(buf-move-down :wk "Buffer move down") "w K" '(buf-move-up :wk "Buffer move up") "w L" '(buf-move-right :wk "Buffer move right")) ) #+end_src * GRAPHICAL USER INTERFACE TWEAKS Let's make GNU Emacs look a little better. ** Disable Menubar, Toolbars and Scrollbars #+begin_src emacs-lisp (menu-bar-mode -1) (tool-bar-mode -1) (scroll-bar-mode -1) #+end_src ** Display Line Numbers and Truncated Lines #+begin_src emacs-lisp (global-display-line-numbers-mode 1) (global-visual-line-mode t) #+end_src * IVY (COUNSEL) + Ivy, a generic completion mechanism for Emacs. + Counsel, a collection of Ivy-enhanced versions of common Emacs commands. + Ivy-rich allows us to add descriptions alongside the commands in M-x. #+begin_src emacs-lisp (use-package counsel :after ivy :diminish :config (counsel-mode)) (use-package ivy :bind ;; ivy-resume resumes the last Ivy-based completion. (("C-c C-r" . ivy-resume) ("C-x B" . ivy-switch-buffer-other-window)) :diminish :custom (setq ivy-use-virtual-buffers t) (setq ivy-count-format "(%d/%d) ") (setq enable-recursive-minibuffers t) :config (ivy-mode)) (use-package all-the-icons-ivy-rich :ensure t :init (all-the-icons-ivy-rich-mode 1)) (use-package ivy-rich :after ivy :ensure t :init (ivy-rich-mode 1) ;; this gets us descriptions in M-x. :custom (ivy-virtual-abbreviate 'full ivy-rich-switch-buffer-align-virtual-buffer t ivy-rich-path-style 'abbrev) :config (ivy-set-display-transformer 'ivy-switch-buffer 'ivy-rich-switch-buffer-transformer)) #+end_src * LANGUAGE SUPPORT Emacs has built-in programming language modes for Lisp, Scheme, DSSSL, Ada, ASM, AWK, C, C++, Fortran, Icon, IDL (CORBA), IDLWAVE, Java, Javascript, M4, Makefiles, Metafont, Modula2, Object Pascal, Objective-C, Octave, Pascal, Perl, Pike, PostScript, Prolog, Python, Ruby, Simula, SQL, Tcl, Verilog, and VHDL. Other languages will require you to install additional modes. #+begin_src emacs-lisp (use-package haskell-mode) (use-package lua-mode) #+end_src * MODELINE The modeline is the bottom status bar that appears in Emacs windows. While you can create your own custom modeline, why go to the trouble when Doom Emacs already has a nice modeline package available. For more information on what is available to configure in the Doom modeline, check out: [[https://github.com/seagle0128/doom-modeline][Doom Modeline]] #+begin_src emacs-lisp (use-package doom-modeline :ensure t :init (doom-modeline-mode 1) :config (setq doom-modeline-height 35 ;; sets modeline height doom-modeline-bar-width 5 ;; sets right bar width doom-modeline-persp-name t ;; adds perspective name to modeline doom-modeline-persp-icon t)) ;; adds folder icon next to persp name #+end_src * NEOTREE Neotree is a file tree viewer. When you open neotree, it jumps to the current file thanks to neo-smart-open. The neo-window-fixed-size setting makes the neotree width be adjustable. NeoTree provides following themes: classic, ascii, arrow, icons, and nerd. Theme can be config'd by setting "two" themes for neo-theme: one for the GUI and one for the terminal. I like to use 'SPC t' for 'toggle' keybindings, so I have used 'SPC t n' for toggle-neotree. | COMMAND | DESCRIPTION | KEYBINDING | |----------------+---------------------------+------------| | neotree-toggle | /Toggle neotree/ | SPC t n | | neotree- dir | /Open directory in neotree/ | SPC d n | #+BEGIN_SRC emacs-lisp (use-package neotree :config (setq neo-smart-open t neo-show-hidden-files t neo-window-width 55 neo-window-fixed-size nil inhibit-compacting-font-caches t projectile-switch-project-action 'neotree-projectile-action) ;; truncate long file names in neotree (add-hook 'neo-after-create-hook #'(lambda (_) (with-current-buffer (get-buffer neo-buffer-name) (setq truncate-lines t) (setq word-wrap nil) (make-local-variable 'auto-hscroll-mode) (setq auto-hscroll-mode nil))))) #+end_src * ORG MODE ** Enabling Table of Contents #+begin_src emacs-lisp (use-package toc-org :commands toc-org-enable :init (add-hook 'org-mode-hook 'toc-org-enable)) #+end_src ** Enabling Org Bullets Org-bullets gives us attractive bullets rather than asterisks. #+begin_src emacs-lisp (add-hook 'org-mode-hook 'org-indent-mode) (use-package org-bullets) (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))) #+end_src ** Disable Electric Indent Org mode source blocks have some really weird and annoying default indentation behavior. I think this has to do with electric-indent-mode, which is turned on by default in Emacs, and the fact that Org defaults to indenting 2 spaces in source blocks. So let's turn it all of that OFF! #+begin_src emacs-lisp (electric-indent-mode -1) (setq org-edit-src-content-indentation 0) #+end_src ** Diminish Org Indent Mode Removes "Ind" from showing in the modeline. #+begin_src emacs-lisp (eval-after-load 'org-indent '(diminish 'org-indent-mode)) #+end_src ** Org Level Headers #+begin_src emacs-lisp (custom-set-faces '(org-level-1 ((t (:inherit outline-1 :height 1.7)))) '(org-level-2 ((t (:inherit outline-2 :height 1.6)))) '(org-level-3 ((t (:inherit outline-3 :height 1.5)))) '(org-level-4 ((t (:inherit outline-4 :height 1.4)))) '(org-level-5 ((t (:inherit outline-5 :height 1.3)))) '(org-level-6 ((t (:inherit outline-5 :height 1.2)))) '(org-level-7 ((t (:inherit outline-5 :height 1.1))))) #+end_src ** Source Code Block Tag Expansion Org-tempo is not a separate package but a module within org that can be enabled. Org-tempo allows for '