This is my Emacs configuration file. My main goal is to make it as fast as possible while keeping it feature-full development environment.
I mainly develop in C# inside Unity, C/C++, Html/Css/Js/Ts and shell scripts sometimes. Git is my preffered versioning system.
NOTE: On Windows preferable fork of emacs is from kinneq. It supports titlebar coloring and native compilation. It is not specifically fork but tools to build emacs with them but author kindly provides compiled packages.
- [ ] Magit support
- [ ] LSP support
- [ ] Code completion
- [ ] Improved org documents
- [ ] OrgRoam or Logseq intergration
Early init is relatively new file which loads before init.el and even gui. It can be used to disable gui elements before they are even able to peek.
;;; early-init.el -*- lexical-binding: t; -*-
Maximize garbage collection at startup. The GC eats up quite a bit of time, easily doubling startup time. The trick is to turn up the memory threshold as early as possible.
Then after emacs is started restore these variables to reasonable sizes, becouse not doing so may cause some rendering issues and slowdowns.
(setq gc-cons-threshold most-positive-fixnum) ; 2^61 bytes
(setq gc-cons-percentage 0.6)
(defun dm/hook--after-startup-gc nil
"Hook function which optimizes garbage collection after emacs initializes."
(defvar dm/gc-cons-threshold 134217728) ; 128mb
;; Lower the garbage collection values.
(setq gc-cons-threshold dm/gc-cons-threshold)
(setq gc-cons-percentage 0.1)
;; Collect garbage after focus has changed.
(if (boundp 'after-focus-change-function)
(add-function :after after-focus-change-function
(lambda ()
(unless (frame-focus-state)
(garbage-collect))))
(add-hook 'after-focus-change-function #'garbage-collect))
;; Collect garbage in minibuffer.
(defun gc-minibuffer-setup-hook nil
(setq gc-cons-threshold (* dm/gc-cons-threshold 2)))
(defun gc-minibuffer-exit-hook nil
(garbage-collect)
(setq gc-cons-threshold dm/gc-cons-threshold))
(add-hook 'minibuffer-setup-hook #'gc-minibuffer-setup-hook)
(add-hook 'minibuffer-exit-hook #'gc-minibuffer-exit-hook))
(add-hook 'emacs-startup-hook #'dm/hook--after-startup-gc)
Disable checking for file handler at startup. Every file opened and loaded by Emacs will run through this list to check for a proper handler for the file, but during startup, it won’t need any of them.
Disabling it and reenabling it after startup makes small diffrence but anything matters.
(defvar default-file-name-handler-alist file-name-handler-alist)
(setq file-name-handler-alist nil)
(defun dm/hook--after-startup-file-name-alist nil
(setq file-name-handler-alist default-file-name-handler-alist)
(makunbound 'default-file-name-handler-alist))
(add-hook 'emacs-startup-hook #'dm/hook--after-startup-file-name-alist)
Disable gui specific modes and variables so they don’t have a chance to peek. Also set default frame parameters.
(setq inhibit-startup-message t)
(setq use-file-dialog nil)
(setq inhibit-compacting-font-caches t)
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
;; (add-to-list 'default-frame-alist '(fullscreen . maximized))
(add-to-list 'default-frame-alist '(alpha . (100 . 100)))
(add-to-list 'default-frame-alist '(width . 200))
(add-to-list 'default-frame-alist '(height . 50))
Disable loading any packages. Since I do it myself with straight.el
,
the default ones would slow down and possibly conflict with straight’s
packages.
(setq package-enable-at-startup nil)
Change default eln-cache
directory.
(when (boundp 'native-comp-eln-load-path)
(startup-redirect-eln-cache
(expand-file-name "var/eln-cache/" user-emacs-directory)))
Silence nativecomp warnings becouse they can be quite obnouctius. Also set some settings for nativecomp.
(setq native-comp-async-report-warnings-errors nil)
(setq native-comp-speed 2)
(setq native-comp-deferred-compilation t)
I’m using straight.el
for managing my packages. Main reason is that
straight loads only packages which i specify and not like
package.el
, which loads everything if is installed. This speeds up
boot times drastically.
Straight also allows me to pin packages to specific commits which is usefull if package breaks at some point.
;;; init.el -*- lexical-binding: t; -*-
(setq straight-base-dir (expand-file-name "var/" user-emacs-directory))
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" straight-base-dir))
(bootstrap-version 5))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
;; (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory)
setup.el
is similar to use-package
but is more light-weight and
easly customizable with custom “commands”.
(straight-use-package '(setup :type git :host nil :repo "https://git.sr.ht/~pkal/setup"))
(require 'setup)
(defun dm/filter-straight-recipe (recipe)
(let* ((plist (cdr recipe))
(name (plist-get plist :straight)))
(cons (if (and name (not (equal name t)))
name
(car recipe))
(plist-put plist :straight nil))))
(setup-define :pkg
(lambda (&rest recipe)
`(straight-use-package ',(dm/filter-straight-recipe recipe)))
:documentation "Install RECIPE via straight.el"
:shorthand #'cadr)
no-littering
is package exacly for that reason. It sets variables
for diffrent files ad folders to be etc/
or var/
based.
(setup (:pkg no-littering)
(setq create-lockfiles nil)
(setq make-backup-files nil)
(setq auto-save-default nil)
(setq auto-save-file-name-transforms `((".*" ,(no-littering-expand-var-file-name "auto-save/") t))))
;; (setq server-auth-dir (no-littering-expand-var-file-name "server/")))
(setup emacs
;; My Information
(setq user-full-name "Dominik Marcinowski")
(setq user-mail-address "dmarcinowski@zoho.com")
;; Clock settings
(setq display-time-24hr-format t)
(setq display-time-load-average -1)
;; Autorevert settings
(setq auto-revert-verbose nil)
(setq auto-revert-use-notify nil)
(setq auto-revert-interval 3)
(setq global-auto-revert-non-file-buffers t)
;; Other settins
(setq custom-file (make-temp-file ""))
(setq bite-compile-warnings '(not free-vars unresolved noroutine lexical make-local))
(setq large-file-warning-threshold nil)
(setq vc-follow-symlinks t)
(setq ad-redefinition-action 'accept)
(setq load-prefer-newer t)
(setq mouse-wheel-progressive-speed nil)
(setq fast-but-imprecise-scrolling nil)
(setq custom-safe-themes t)
(setq enable-local-variables :all)
(setq jit-lock-defer-time 0)
(setq read-extended-command-predicate #'command-completion-default-include-p)
(:global "<escape>" 'keyboard-escape-quit
"C-=" 'text-scale-increase
"C-+" 'text-scale-increase
"C--" 'text-scale-decrease)
(defalias 'yes-or-no-p 'y-or-n-p)
(add-hook 'after-init-hook #'electric-pair-mode)
(add-hook 'after-init-hook #'electric-layout-mode)
(add-hook 'after-init-hook #'global-auto-revert-mode)
(add-hook 'after-init-hook #'global-subword-mode)
(add-hook 'after-init-hook #'column-number-mode)
(add-hook 'after-init-hook #'save-place-mode))
(setup recentf
(setq recentf-max-saved-items 2048)
(setq recentf-exclude '("/tmp/" "/ssh:" "/sudo:"
"/.emacs.d/etc/*" "/.emacs.d/var/*"
"/agenda/*" "/roam/*"
"recentf$"
"\\.mkv$" "\\.mp[34]$" "\\.avi$" "\\.pdf$" "\\.docx?$" "\\.xlsx?$"
"\\.sub$" "\\.srt$" "\\.ass$"))
(run-at-time nil (* 5 60) #'recentf-save-list)
(add-hook 'after-init-hook #'recentf-mode))
(setup dired
(setq dired-listing-switches "-lah --group-directories-first"
dired-recursive-copies 'always
dired-recursive-deletes 'always
dired-dwim-target t
delete-by-moving-to-trash t))
(setq dm/font-monospace "Cascadia Code")
(setq dm/font-variable "Segoe UI")
I used vim for far too long and not having vim bindings is just painful.
(setup (:pkg undo-tree))
(setup (:pkg evil-collection))
(setup (:pkg evil-commentary))
(setup (:pkg evil)
(setq undo-tree-auto-save-history t
evil-undo-system 'undo-tree)
(setq evil-want-C-u-scroll t
evil-want-C-d-scroll t
evil-want-C-i-jump nil
evil-want-integration t
evil-want-keybinding nil
evil-split-window-below t
evil-split-window-right t
evil-respect-visual-line-mode 1)
(setq evil-collection-outline-bind-tab-p t)
(evil-mode)
(global-undo-tree-mode)
(evil-collection-init)
(evil-commentary-mode)
(setq evil-want-keybinding t))
General is a package to configure leader like bindings with ease.
I use SPC
and C-SPC
for my leader key.
(setup (:pkg general)
(general-evil-setup)
(general-create-definer dm/general-leader
:states '(normal insert visual emacs)
:keymaps 'override
:prefix "SPC"
:global-prefix "C-SPC")
(dm/general-leader
"C-SPC" #'(execute-extended-command :wk "command")
"SPC" #'(execute-extended-command :wk "command")
"." #'(find-file :wk "find file")
"h" #'(:keymap help-map t :wk "help")
"u" #'(universal-argument :wk "universal prefix")
"q" #'(evil-quit :wk "quit")
"Q" #'(evil-quit-all :wk "quit all")
"f" #'(:ignore t :wk "file")
"ff" #'(find-file :wk "find file")
"fd" #'(dired-at-point :wk "dired at file")
"fs" #'(save-buffer :wk "save file")
"fc" #'(find-file "~/.emacs.d/" :wk "config")
"b" #'(:ignore t :wk "buffer")
"bi" #'(ibuffer-jump :wk "ibuffer")
"bb" #'(switch-to-buffer :wk "switch buffer")
"bk" #'(kill-this-buffer :wk "kill this buffer")
"br" #'(revert-buffer :wk "reload buffer")
"c" #'(:ignore t :wk "code")
"s" #'(:ignore t :wk "search")))
Which key is nice gui for displaying possible bindings so I don’t have to blindly type them. I’m just a human, I don’t remember them all.
(setup (:pkg which-key)
(setq which-key-idle-delay 0.3)
(which-key-mode))
Dashboard is naice landing buffer to select recent files, projects, etc.
(setup (:pkg dashboard)
(setq dashboard-center-content t
dashboard-startup-banner (no-littering-expand-etc-file-name "dashboard/logo.png")
;; dashboard-items '((projects . 10)
;; (recents . 5)
;; (agenda . 5))
dashboard-banner-logo-title nil
dashboard-set-footer nil
dashboard-set-file-icons t
dashboard-set-heading-icons t
dashboard-set-navigator t
dashboard-week-agenda t
dashboard-filter-agenda-entry 'dashboard-filter-agenda-by-todo
initial-buffer-choice (lambda () (get-buffer dashboard-buffer-name)))
(dashboard-setup-startup-hook)
(dashboard-modify-heading-icons '((recents . "file-text")
(bookmarks . "book"))))
;; (setup (:pkg solaire-mode))
(setup (:pkg rainbow-mode))
(setup (:pkg rainbow-delimiters))
(setup (:pkg hl-todo))
(setup (:pkg all-the-icons))
(setup (:pkg all-the-icons-dired))
(setup (:pkg all-the-icons-ibuffer))
(setup (:pkg all-the-icons-completion))
;; (setup (:pkg twilight-bright-theme))
(setup (:pkg doom-themes)
(setq doom-themes-enable-bold t)
(setq doom-themes-enable-italic t)
(doom-themes-visual-bell-config)
(doom-themes-org-config))
(setup (:pkg doom-modeline)
(setq doom-modeline-height 28)
(setq doom-modeline-bar-width 6)
(setq doom-modeline-hud nil)
(setq doom-modeline-major-mode-icon t)
(setq doom-modeline-buffer-modification-icon t)
(setq doom-modeline-buffer-state-icon t)
(setq doom-modeline-indent-info t)
(setq doom-modeline-minor-modes nil)
(setq doom-modeline-buffer-file-name-style 'truncate-except-project)
(add-hook 'after-init-hook #'size-indication-mode)
(add-hook 'after-init-hook #'display-time-mode))
(defun dm/setup--font-faces nil
"Sets basic font faces."
(set-face-attribute 'default nil :font (font-spec :family dm/font-monospace :size 14 :weight 'regular))
(set-face-attribute 'fixed-pitch nil :font (font-spec :family dm/font-monospace :size 14 :weight 'regular))
(set-face-attribute 'variable-pitch nil :font (font-spec :family dm/font-variable :size 14 :weight 'regular))
(set-fontset-font t 'unicode dm/font-monospace))
(defun dm/setup--utf8-encoding nil
"Sets UTF-8 encoding everywhere."
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-file-name-coding-system 'utf-8)
(set-buffer-file-coding-system 'utf-8)
(if (eq system-type 'windows-nt)
(progn
(set-clipboard-coding-system 'utf-16-le)
(set-selection-coding-system 'utf-16-le))
(progn
(set-clipboard-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)))
(setq locale-coding-system 'utf-8)
(setq coding-system-for-read 'utf-8)
(setq coding-system-for-write 'utf-8)
(setq default-process-coding-system '(utf-8-unix . utf-8-unix))
(when (display-graphic-p)
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))))
(defun dm/setup-fonts nil
(dm/setup--font-faces)
(dm/setup--utf8-encoding))
(defun dm/set-theme (&optional dark-theme)
"Set theme depending on system preferences."
(interactive)
;; (load-theme 'modus-vivendi t)
(or dark-theme (setq dark-theme nil))
(if (or (= (w32-read-registry 'HKCU "Software/Microsoft/Windows/CurrentVersion/Themes/Personalize" "AppsUseLightTheme") 0)
dark-theme)
(load-theme 'doom-one t)
(load-theme 'doom-one-light t))
(dm/setup-fonts))
(defun dm/setup-theme nil
(doom-modeline-mode)
(global-hl-todo-mode)
;; (solaire-global-mode 1)
(all-the-icons-ibuffer-mode 1)
(all-the-icons-completion-mode 1)
(dm/set-theme))
(defun dm/setup-file-theme nil
(rainbow-mode 1)
(rainbow-delimiters-mode 1)
(hl-todo-mode 1)
(display-line-numbers-mode 1))
(add-hook 'after-init-hook #'dm/setup-theme)
(add-hook 'server-after-make-frame-hook #'dm/setup-theme)
(add-hook 'prog-mode-hook #'dm/setup-file-theme)
(add-hook 'text-mode-hook #'dm/setup-file-theme)
(add-hook 'conf-mode-hook #'dm/setup-file-theme)
(add-hook 'dired-mode-hook #'all-the-icons-dired-mode)
(setup (:pkg vertico)
(setq vertico-cycle t)
(setq vertico-resize nil)
(setq vertico-sort-function 'vertico-sort-history-alpha)
(setq vertico-count-format '("%-6s " . "(%s/%s)"))
(setq vertico-count 15)
(add-hook 'after-init-hook #'vertico-mode))
(setup (:pkg save-history)
(add-hook 'vertico-mode-hook #'savehist-mode))
(setup (:pkg marginalia)
(add-hook 'vertico-mode-hook #'marginalia-mode))
(setup (:pkg orderless)
(setq completion-styles '(orderless basic))
(setq completion-category-defaults nil)
(setq completion-category-overrides '((file (styles partial-completion)))))
Here Is setup languages I use.
(setup (:pkg ahk-mode))
(setup (:pkg yaml-mode))
(setup (:pkg markdown-mode))
(setup (:pkg csharp-mode))
(setup (:pkg magit))
(setup (:pkg (org-auto-tangle :type git :host nil :repo "https://github.com/yilkalargaw/org-auto-tangle"))
(add-hook 'org-mode-hook 'org-auto-tangle-mode))