25 KiB
DT's GNU Emacs Config
- TABLE OF CONTENTS
- IMPORTANT PROGRAMS TO LOAD FIRST
- ALL THE ICONS
- BACKUP FILES
- COMPANY
- DASHBOARD
- DIMINISH
- DIRED
- EVIL
- FLYCHECK
- FONTS
- GENERAL KEYBINDINGS
- GRAPHICAL USER INTERFACE TWEAKS
- IVY (COUNSEL)
- LANGUAGE SUPPORT
- MODELINE
- NEOTREE
- ORG MODE
- PROJECTILE
- RAINBOW MODE
- SHELLS AND TERMINALS
- SUDO EDIT
- THEME
- TRANSPARENCY
- WHICH-KEY
TABLE OF CONTENTS toc
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
(add-to-list 'load-path "~/.config/emacs/scripts/")
Sourcing the scripts
(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)
ALL THE ICONS
This is an icon set that can be used with dashboard, dired, ibuffer and other Emacs programs.
(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))))
BACKUP FILES
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.
(setq backup-directory-alist '((".*" . "~/.Trash")))
COMPANY
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, <return> to complete or <tab> to complete the common part.
(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))
DASHBOARD
Emacs Dashboard is an extensible startup screen showing you recent files, bookmarks, agenda items and an Emacs banner.
(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))
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.
(use-package diminish)
DIRED
(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)
)
EVIL
Evil is an extensible vi/vim layer for Emacs. Because…let's face it. The Vim keybindings are just plain better.
;; 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.
(setq evil-want-keybinding nil)
(setq evil-vsplit-window-right t)
(setq evil-split-window-below t)
(evil-mode))
(use-package evil-collection
:after evil
:config
(setq evil-collection-mode-list '(dashboard dired ibuffer))
(evil-collection-init))
(use-package evil-tutor)
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, read this.
(use-package flycheck
:ensure t
:defer t
:diminish
:init (global-flycheck-mode))
FONTS
Defining the various fonts that Emacs will use.
Setting the Font Face
(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)
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.
(global-set-key (kbd "C-=") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)
(global-set-key (kbd "<C-wheel-up>") 'text-scale-increase)
(global-set-key (kbd "<C-wheel-down>") 'text-scale-decrease)
GENERAL KEYBINDINGS
(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 "Buffer")
"b b" '(switch-to-buffer :wk "Switch buffer")
"b i" '(ibuffer :wk "Ibuffer")
"b k" '(kill-this-buffer :wk "Kill this buffer")
"b n" '(next-buffer :wk "Next buffer")
"b p" '(previous-buffer :wk "Previous buffer")
"b r" '(revert-buffer :wk "Reload buffer"))
(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 b" '(describe-bindings :wk "Describe bindings")
"h f" '(describe-function :wk "Describe function")
"h t" '(load-theme :wk "Load theme")
"h v" '(describe-variable :wk "Describe variable")
"h r r" '((lambda () (interactive)
(load-file "~/.config/emacs/init.el")
(ignore (elpaca-process-queues)))
:wk "Reload emacs config"))
(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 l" '(display-line-numbers-mode :wk "Toggle line numbers")
"t n" '(neotree-toggle :wk "Toggle neotree file viewer")
"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"))
)
GRAPHICAL USER INTERFACE TWEAKS
Let's make GNU Emacs look a little better.
Disable Menubar, Toolbars and Scrollbars
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
Display Line Numbers and Truncated Lines
(global-display-line-numbers-mode 1)
(global-visual-line-mode t)
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.
(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))
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.
(use-package haskell-mode)
(use-package lua-mode)
MODELINE
The modeline is the bottom status bar that appears in Emacs windows. For more information on what is available to configure in the Doom modeline, check out: https://github.com/seagle0128/doom-modeline
(use-package doom-modeline
:ensure t
:init (doom-modeline-mode 1)
:config
(setq doom-modeline-height 30 ;; 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
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 configed 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 |
(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)))))
ORG MODE
Enabling Table of Contents
(use-package toc-org
:commands toc-org-enable
:init (add-hook 'org-mode-hook 'toc-org-enable))
Enabling Org Bullets
Org-bullets gives us attractive bullets rather than asterisks.
(add-hook 'org-mode-hook 'org-indent-mode)
(use-package org-bullets)
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))
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!
(electric-indent-mode -1)
(setq org-edit-src-content-indentation 0)
Diminish Org Indent Mode
Removes "Ind" from showing in the modeline.
(eval-after-load 'org-indent '(diminish 'org-indent-mode))
Org Level Headers
(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)))))
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 '<s' followed by TAB to expand to a begin_src tag. Other expansions available include:
| Typing the below + TAB | Expands to … |
|---|---|
| <a | '#+BEGIN_EXPORT ascii' … '#+END_EXPORT |
| <c | '#+BEGIN_CENTER' … '#+END_CENTER' |
| <C | '#+BEGIN_COMMENT' … '#+END_COMMENT' |
| <e | '#+BEGIN_EXAMPLE' … '#+END_EXAMPLE' |
| <E | '#+BEGIN_EXPORT' … '#+END_EXPORT' |
| <h | '#+BEGIN_EXPORT html' … '#+END_EXPORT' |
| <l | '#+BEGIN_EXPORT latex' … '#+END_EXPORT' |
| <q | '#+BEGIN_QUOTE' … '#+END_QUOTE' |
| <s | '#+BEGIN_SRC' … '#+END_SRC' |
| <v | '#+BEGIN_VERSE' … '#+END_VERSE' |
(require 'org-tempo)
PROJECTILE
Projectile is a project interaction library for Emacs. It should be noted that many projectile commands do not work if you have set "fish" as the "shell-file-name" for Emacs. I had initially set "fish" as the "shell-file-name" in the Vterm section of this config, but oddly enough I changed it to "bin/sh" and projectile now works as expected, and Vterm still uses "fish" because my default user "sh" on my Linux system is "fish".
(use-package projectile
:config
(projectile-mode 1))
RAINBOW MODE
Display the actual color as a background for any hex color value (ex. #ffffff). The code block below enables rainbow-mode in all programming modes (prog-mode) as well as org-mode, which is why rainbow works in this document.
(use-package rainbow-mode
:diminish
:hook org-mode prog-mode)
SHELLS AND TERMINALS
In my configs, all of my shells (bash, fish, zsh and the ESHELL) require my shell-color-scripts-git package to be installed. On Arch Linux, you can install it from the AUR. Otherwise, go to my shell-color-scripts repository on GitLab to get it.
Eshell
Eshell is an Emacs 'shell' that is written in Elisp.
(use-package eshell-toggle
:custom
(eshell-toggle-size-fraction 3)
(eshell-toggle-use-projectile-root t)
(eshell-toggle-run-command nil)
(eshell-toggle-init-function #'eshell-toggle-init-ansi-term))
(use-package eshell-syntax-highlighting
:after esh-mode
:config
(eshell-syntax-highlighting-global-mode +1))
;; eshell-syntax-highlighting -- adds fish/zsh-like syntax highlighting.
;; eshell-rc-script -- your profile for eshell; like a bashrc for eshell.
;; eshell-aliases-file -- sets an aliases file for the eshell.
(setq eshell-rc-script (concat user-emacs-directory "eshell/profile")
eshell-aliases-file (concat user-emacs-directory "eshell/aliases")
eshell-history-size 5000
eshell-buffer-maximum-lines 5000
eshell-hist-ignoredups t
eshell-scroll-to-bottom-on-input t
eshell-destroy-buffer-when-process-dies t
eshell-visual-commands'("bash" "fish" "htop" "ssh" "top" "zsh"))
Vterm
Vterm is a terminal emulator within Emacs. The 'shell-file-name' setting sets the shell to be used in M-x shell, M-x term, M-x ansi-term and M-x vterm. By default, the shell is set to 'fish' but could change it to 'bash' or 'zsh' if you prefer.
(use-package vterm
:config
(setq shell-file-name "/bin/sh"
vterm-max-scrollback 5000))
Vterm-Toggle
vterm-toggle toggles between the vterm buffer and whatever buffer you are editing.
(use-package vterm-toggle
:after vterm
:config
(setq vterm-toggle-fullscreen-p nil)
(setq vterm-toggle-scope 'project)
(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-at-bottom)
;;(display-buffer-reuse-window display-buffer-in-direction)
;;display-buffer-in-direction/direction/dedicated is added in emacs27
;;(direction . bottom)
;;(dedicated . t) ;dedicated is supported in emacs27
(reusable-frames . visible)
(window-height . 0.4))))
SUDO EDIT
sudo-edit gives us the ability to open files with sudo privileges or switch over to editing with sudo privileges if we initially opened the file without such privileges.
(use-package sudo-edit
:config
(dt/leader-keys
"fu" '(sudo-edit-find-file :wk "Sudo find file")
"fU" '(sudo-edit :wk "Sudo edit file")))
THEME
The first line below designates the directory where will place all of our custom-made themes, which I have created only one (dtmacs) You can create your own Emacs themes with the help of the Emacs Theme Editor. I also am installing doom-themes because it contains a huge collection of themes. M-x load-theme will list all of the themes available.
(add-to-list 'custom-theme-load-path "~/.config/emacs/themes/")
(use-package doom-themes
:config
(setq doom-themes-enable-bold t ; if nil, bold is universally disabled
doom-themes-enable-italic t) ; if nil, italics is universally disabled
;; Sets the default theme to load!!!
(load-theme 'doom-one t)
;; Enable custom neotree theme (all-the-icons must be installed!)
(doom-themes-neotree-config)
;; Corrects (and improves) org-mode's native fontification.
(doom-themes-org-config))
TRANSPARENCY
With Emacs version 29, true transparency has been added. I have turned transparency off by setting the alpha to '100'. If you want some slight transparency, try setting alpha to '90'. Of course, if you set alpha to '0', the background of Emacs would completely transparent.
(add-to-list 'default-frame-alist '(alpha-background . 100)) ; For all new frames henceforth
WHICH-KEY
(use-package which-key
:init
(which-key-mode 1)
:diminish
:config
(setq which-key-side-window-location 'bottom
which-key-sort-order #'which-key-key-order
which-key-allow-imprecise-window-fit nil
which-key-sort-uppercase-first nil
which-key-add-column-padding 1
which-key-max-display-columns nil
which-key-min-display-lines 6
which-key-side-window-slot -10
which-key-side-window-max-height 0.25
which-key-idle-delay 0.8
which-key-max-description-length 25
which-key-allow-imprecise-window-fit nil
which-key-separator " → " ))