Improving startup time and adding important packages

This commit is contained in:
Joseph Ferano 2022-08-20 13:43:53 +07:00
parent 795bbf3b46
commit 73679a610d
2 changed files with 367 additions and 146 deletions

View File

@ -1,161 +1,372 @@
#+TITLE: Emacs Config
#+AUTHOR: Joseph Ferano
#+PROPERTY: header-args:emacs-lisp :tangle ./init.el
#+STARTUP: overview
#+TOC: true
** Package Management
** Early Init
*** Garbage Collection
*** Straight.el
The default Garbage Collector is triggered at 800 KB, way too conservative, let's bump to 512 MB.
Garbage collection is a big contributor to startup times. This fends it off, then is reset later by
enabling `gcmh-mode'. Not resetting it will cause stuttering/freezes.
#+begin_src emacs-lisp :tangle ./early-init.el
;; -*- lexical-binding: t; -*-
(defvar default-file-name-handler-alist file-name-handler-alist)
(setq file-name-handler-alist nil)
(setq gc-cons-threshold (expt 2 32))
(add-hook 'emacs-startup-hook
(lambda ()
"Restore defalut values after init."
(setq file-name-handler-alist default-file-name-handler-alist)
(if (boundp 'after-focus-change-function)
(add-function :after after-focus-change-function
(lambda ()
(unless (frame-focus-state)
(garbage-collect))))
(add-hook 'focus-out-hook 'garbage-collect))))
(setq native-comp-deferred-compilation nil)
#+end_src
#+begin_src emacs-lisp :tangle ./early-init.el
(setq max-specpdl-size 1200)
(setq max-lisp-eval-depth 800)
(add-hook 'window-setup-hook
(lambda ()
(setq-default inhibit-redisplay nil
inhibit-message nil)
(redisplay)))
#+end_src
*** Setup
Disable package.el, since we will be using straight.el. According to the straight.el
documentation;
#+BEGIN_QUOTE
While it is technically possible to use both package.el and straight.el at the same time, there is no real reason to, and it might result in oddities like packages getting loaded more than once.
#+END_QUOTE
Either way, if you need to quickly install a package for testing, you can just run
=(straight-use-package)= interactively.
#+BEGIN_SRC emacs-lisp :tangle ./early-init.el
(setq package-enable-at-startup nil)
#+END_SRC
*** Enhancements
Prioritize old byte-compiled source files over newer sources. It saves us a little IO time to skip all the mtime checks on each lookup.
#+begin_src emacs-lisp :tangle ./early-init.el
(setq load-prefer-newer nil)
#+end_src
#+begin_src emacs-lisp :tangle ./early-init.el
(set-language-environment "UTF-8")
(setq default-input-method nil)
;;; early-init.el ends here
#+end_src
** Straight.el
For now, use [[https://github.com/radian-software/straight.el][straight.el]] until [[https://github.com/progfolio/elpaca
][elpaca]] is ready for production use.
First, disable package.el during early init
#+BEGIN_SRC emacs-lisp :tangle ./early-init.el
(setq package-enable-at-startup nil)
#+END_SRC
Then bootstrap
#+BEGIN_SRC emacs-lisp
(declare-function elpaca-generate-autoloads "elpaca")
(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
(when-let ((elpaca-repo (expand-file-name "repos/elpaca/" elpaca-directory))
(elpaca-build (expand-file-name "builds/elpaca/" elpaca-directory))
(elpaca-target (if (file-exists-p elpaca-build) elpaca-build elpaca-repo))
(elpaca-url "https://www.github.com/progfolio/elpaca.git")
((add-to-list 'load-path elpaca-target))
((not (file-exists-p elpaca-repo)))
(buffer (get-buffer-create "*elpaca-bootstrap*")))
(condition-case-unless-debug err
(progn
(unless (zerop (call-process "git" nil buffer t "clone" elpaca-url elpaca-repo))
(error "%s" (list (with-current-buffer buffer (buffer-string)))))
(byte-recompile-directory elpaca-repo 0 'force)
(require 'elpaca)
(elpaca-generate-autoloads "elpaca" elpaca-repo)
(kill-buffer buffer))
((error)
(delete-directory elpaca-directory 'recursive)
(with-current-buffer buffer
(goto-char (point-max))
(insert (format "\n%S" err))
(display-buffer buffer)))))
(require 'elpaca-autoloads)
(add-hook 'after-init-hook #'elpaca-process-queues)
(elpaca (elpaca :host github :repo "progfolio/elpaca"))
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 6))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
#+END_SRC
*** General Settings
**** Misc Stuff
** Misc Stuff
#+begin_SRC emacs-lisp
(setq vc-follow-symlinks t) ; Visit real file when editing a symlink without prompting.
(global-auto-revert-mode t) ; Revert buffer's file when the file changes on disk
;; (straight-use-package 'benchmark-init)
;; (require 'benchmark-init)
;; (add-hook 'after-init-hook 'benchmark-init/deactivate)
(fset 'yes-or-no-p 'y-or-n-p)
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(setq vc-follow-symlinks t) ; Visit real file when editing a symlink without prompting.
(global-auto-revert-mode t) ; Revert buffer's file when the file changes on disk
(setq gc-cons-threshold 50000000)
(setq max-specpdl-size 1200)
(setq max-lisp-eval-depth 800)
(setq large-file-warning-threshold 100000000)
(setq confirm-kill-emacs 'y-or-n-p)
(setq use-dialog-box nil)
(fset 'yes-or-no-p 'y-or-n-p)
(setq backup-by-copying t
delete-old-versions t
kept-new-versions 6
kept-old-versions 2
version-control t
backup-directory-alist '((".*" . (expand-file-name "backups" user-emacs-directory))))
(setq large-file-warning-threshold 100000000)
(setq backup-directory-alist `((".*" . ,(expand-file-name "backups" user-emacs-directory))))
(setq backup-by-copying t
delete-old-versions t
kept-new-versions 6
kept-old-versions 2
version-control t)
#+END_SRC
**** Visuals
** Visuals
Use Dashboard.el. First load `all-the-icons` for nicer rendering
#+begin_src emacs-lisp
(setq inhibit-startup-screen t)
(add-hook 'text-mode-hook (lambda () (setq fill-column 100) (turn-on-auto-fill)))
(straight-use-package 'all-the-icons)
(straight-use-package 'dashboard)
(dashboard-setup-startup-hook)
(setq-default display-line-numbers 'relative)
(make-variable-buffer-local 'global-hl-line-mode)
(set-window-margins nil 0)
(setq-default right-fringe-width 10)
(setq scroll-margin 0
scroll-conservatively 100000
scroll-preserve-screen-position 1)
(setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*")))
(setq dashboard-startup-banner 'logo)
(setq dashboard-center-content t)
(setq dashboard-set-file-icons t)
(setq dashboard-set-heading-icons t)
(add-hook 'dashboard-mode-hook (lambda () (setq-local line-spacing 12)))
#+end_src
(global-hl-line-mode +1)
(column-number-mode +1)
Setup other stuff
(scroll-bar-mode -1)
(tool-bar-mode -1)
(menu-bar-mode -1)
(tooltip-mode -1)
#+begin_src emacs-lisp
(add-hook 'text-mode-hook (lambda () (setq fill-column 100) (turn-on-auto-fill)))
(setq custom-safe-themes t)
;; (load-theme 'doom-vibrant t)
;; (load-theme 'doom-flatwhite t)
(setq-default display-line-numbers 'relative)
(make-variable-buffer-local 'global-hl-line-mode)
(dolist (mode '( dashboard-mode-hook org-mode-hook term-mode-hook eww-mode-hook vterm-mode-hook
eshell-mode-hook dired-mode-hook shell-mode-hook magit-mode-hook))
(add-hook mode (lambda () (display-line-numbers-mode 0))))
(set-window-margins nil 0)
(setq-default right-fringe-width 10)
(setq scroll-margin 0
scroll-conservatively 100000
scroll-preserve-screen-position 1)
(global-hl-line-mode +1)
(column-number-mode +1)
(scroll-bar-mode -1)
(tool-bar-mode -1)
(menu-bar-mode -1)
(tooltip-mode -1)
(modify-all-frames-parameters
'((right-divider-width . 5)
(internal-border-width . 10)))
(setq inhibit-startup-screen t)
(straight-use-package 'doom-themes)
(setq custom-safe-themes t)
(load-theme 'doom-vibrant t)
;; (load-theme 'doom-flatwhite t)
(straight-use-package 'ligature)
(global-ligature-mode)
(straight-use-package 'highlight-quoted)
(add-hook 'emacs-lisp-mode-hook 'highlight-quoted-mode)
(straight-use-package 'nano-modeline)
(nano-modeline-mode)
#+end_src
** Text
#+begin_src emacs-lisp
(set-face-attribute 'default nil :font "Fira Code Nerd Font" :height 105)
(setq-default c-basic-offset 4) ;; This is annoying
(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
(setq-default line-spacing 5)
(setq indent-line-function 'insert-tab)
(set-default 'truncate-lines nil)
(set-default 'truncate-partial-width-windows nil)
(add-hook 'before-save-hook 'whitespace-cleanup)
#+end_src
** Org Mode
#+begin_src emacs-lisp
(require 'org)
(setq org-todo-keywords '((sequence "TODO" "IN-PROGRESS" "|" "DONE" "BACKLOG")))
(setq org-agenda-files '("~/todo.org"))
(straight-use-package 'org-bullets)
(defun joe/org-hook () (org-bullets-mode) (org-indent-mode))
(add-hook 'org-mode-hook 'joe/org-hook)
(require 'org-tempo)
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(setq org-edit-src-content-indentation 0)
#+end_src
** VEMCO (Vertico Embark Marginalia Consult Orderless)
#+begin_src emacs-lisp
(straight-use-package '(vertico :files (:defaults "extensions/*") :includes (vertico-directory)))
;; :bind (:map vertico-map
;; ("\M-G" . vertico-multiform-mode)
;; ("\M-e" . embark-act)))
(vertico-mode)
(require 'savehist)
(savehist-mode)
(straight-use-package 'vertico-directory)
;; :bind (:map vertico-map
;; ("RET" . vertico-directory-enter)
;; ("DEL" . vertico-directory-delete-char)
;; ("M-DEL" . vertico-directory-delete-word))
;; :hook (rfn-eshadow-update-overlay . vertico-directory-tidy))
(straight-use-package 'embark)
(straight-use-package 'embark-consult)
(straight-use-package 'marginalia)
(marginalia-mode)
(setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
(straight-use-package 'consult)
(straight-use-package 'orderless)
(setq completion-styles '(orderless basic)
completion-category-overrides '((file (styles basic partial-completion))))
#+end_src
** Dirvish/Dired
#+begin_src emacs-lisp
(straight-use-package 'dirvish)
(dirvish-override-dired-mode)
(setq delete-by-moving-to-trash t)
(setq dired-dwim-target t)
(dirvish-define-preview exa (file)
"Use `exa' to generate directory preview."
:require ("exa") ; tell Dirvish to check if we have the executable
(when (file-directory-p file) ; we only interest in directories here
`(shell . ("exa" "--color=always" "-al" ,file)))) ; use the command output as preview
(add-to-list 'dirvish-preview-dispatchers 'exa)
(setq dired-listing-switches "-l --almost-all --human-readable --time-style=long-iso --group-directories-first --no-group")
(setq dirvish-preview-dispatchers (cl-substitute 'pdf-preface 'pdf dirvish-preview-dispatchers))
#+end_src
**** Text
** Terminals/Shells
#+begin_src emacs-lisp
(set-face-attribute 'default nil :font "Fira Code Nerd Font" :height 105)
(setq-default c-basic-offset 4) ;; This is annoying
(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
(setq indent-line-function 'insert-tab)
(set-default 'truncate-lines nil)
(set-default 'truncate-partial-width-windows nil)
(setq-default line-spacing 5)
(add-hook 'dashboard-mode-hook (lambda () (setq-local line-spacing 12)))
(add-hook 'before-save-hook 'whitespace-cleanup)
(straight-use-package 'vterm)
(setq vterm-shell "/bin/fish")
(setq vterm-timer-delay 0.01)
(setq vterm-buffer-name-string "VTerm - %s")
(setq vterm-max-scrollback 100000)
#+end_src
*** Org Mode
** Undo Tree
#+begin_src emacs-lisp
(require 'org)
(require 'org-tempo)
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(setq org-agenda-files '("~/todo.org"))
(add-hook 'org-mode-hook
'(defun joe/org-mode-setup ()
((org-bullets-mode)
(org-indent-mode))))
(setq org-todo-keywords '((sequence "TODO" "IN-PROGRESS" "|" "DONE" "BACKLOG")))
;; (elpaca-use-package 'org-bullets)
#+end_src
*** VEMCO (Vertico Embark Marginalia Consult Orderless)
#+begin_src emacs-lisp
(elpaca-use-package 'vertico)
(vertico-mode)
(vertico-multiform-mode)
(define-key vertico-map "\M-G" #'vertico-multiform-mode)
(elpaca-use-package 'embark)
(elpaca-use-package 'embark-consult)
(define-key vertico-map "\M-e" #'embark-act)
(elpaca-use-package 'marginalia)
(marginalia-mode t)
(setq marginalia-annotators
'(marginalia-annotators-heavy marginalia-annotators-light nil))
(elpaca-use-package 'orderless)
(setq completion-styles '(orderless basic)
completion-category-overrides '((file (styles basic partial-completion))))
(elpaca-use-package 'savehist)
(savehist-mode)
(straight-use-package 'undo-tree)
(require 'undo-tree)
(global-undo-tree-mode)
(setq undo-tree-visualizer-diff t)
(setq undo-tree-history-directory-alist `(("." . ,(expand-file-name "undo" user-emacs-directory))))
#+end_src
** Text Editor
#+begin_src emacs-lisp
(straight-use-package 'meow)
(require 'meow)
(defun meow-setup ()
(setq meow-cheatsheet-layout meow-cheatsheet-layout-qwerty)
(meow-motion-overwrite-define-key
'("j" . meow-next)
'("k" . meow-prev)
'("<escape>" . ignore))
(meow-leader-define-key
;; SPC j/k will run the original command in MOTION state.
'("j" . "H-j")
'("k" . "H-k")
;; Use SPC (0-9) for digit arguments.
'("1" . meow-digit-argument)
'("2" . meow-digit-argument)
'("3" . meow-digit-argument)
'("4" . meow-digit-argument)
'("5" . meow-digit-argument)
'("6" . meow-digit-argument)
'("7" . meow-digit-argument)
'("8" . meow-digit-argument)
'("9" . meow-digit-argument)
'("0" . meow-digit-argument)
'("/" . meow-keypad-describe-key)
'("?" . meow-cheatsheet))
(meow-normal-define-key
'("0" . meow-expand-0)
'("9" . meow-expand-9)
'("8" . meow-expand-8)
'("7" . meow-expand-7)
'("6" . meow-expand-6)
'("5" . meow-expand-5)
'("4" . meow-expand-4)
'("3" . meow-expand-3)
'("2" . meow-expand-2)
'("1" . meow-expand-1)
'("-" . negative-argument)
'(";" . meow-reverse)
'("," . meow-inner-of-thing)
'("." . meow-bounds-of-thing)
'("[" . meow-beginning-of-thing)
'("]" . meow-end-of-thing)
'("a" . meow-append)
'("A" . meow-open-below)
'("b" . meow-back-word)
'("B" . meow-back-symbol)
'("c" . meow-change)
'("d" . meow-delete)
'("D" . meow-backward-delete)
'("e" . meow-next-word)
'("E" . meow-next-symbol)
'("f" . meow-find)
'("g" . meow-cancel-selection)
'("G" . meow-grab)
'("h" . meow-left)
'("H" . meow-left-expand)
'("i" . meow-insert)
'("I" . meow-open-above)
'("j" . meow-next)
'("J" . meow-next-expand)
'("k" . meow-prev)
'("K" . meow-prev-expand)
'("l" . meow-right)
'("L" . meow-right-expand)
'("m" . meow-join)
'("n" . meow-search)
'("o" . meow-block)
'("O" . meow-to-block)
'("p" . meow-yank)
'("q" . meow-quit)
'("Q" . meow-goto-line)
'("r" . meow-replace)
'("R" . meow-swap-grab)
'("s" . meow-kill)
'("t" . meow-till)
'("u" . meow-undo)
'("U" . meow-undo-in-selection)
'("v" . meow-visit)
'("w" . meow-mark-word)
'("W" . meow-mark-symbol)
'("x" . meow-line)
'("X" . meow-goto-line)
'("y" . meow-save)
'("Y" . meow-sync-grab)
'("z" . meow-pop-selection)
'("'" . repeat)
'("<escape>" . ignore)))
(meow-setup)
;; (meow-global-mode t)
#+end_src
** Magit
#+begin_src emacs-lisp
(straight-use-package 'magit)
#+end_src
* COMMENT Local variables
;; Local Variables:
;; eval: (add-hook 'after-save-hook '(lambda () (org-babel-tangle)) nil t)

View File

@ -5,8 +5,6 @@
delete-old-versions t)
(setq auto-save-file-name-transforms `((".*" ,temporary-file-directory t)))
(setq user-full-name "Joseph Ferano"
user-mail-address "joseph@ferano.io")
(setq gc-cons-threshold 50000000)
(setq large-file-warning-threshold 100000000)
(global-auto-revert-mode t)
@ -21,8 +19,8 @@
(put 'narrow-to-region 'disabled nil)
(require 'server)
(if (not (server-running-p)) (server-start))
;; (require 'server)
;; (if (not (server-running-p)) (server-start))
(add-hook 'prog-mode (lambda () (modify-syntax-entry ?_ "w")))
(setq default-directory "/home/joe")
@ -127,9 +125,19 @@ all of the evil keybindings in buffers like magit, without compromises."
'("aaa4c36ce00e572784d424554dcc9641c82d1155370770e231e10c649b59a074" default))
'(flycheck-color-mode-line-face-to-color 'mode-line-buffer-id)
'(frame-background-mode 'dark)
'(ignored-local-variable-values
'((eval add-hook 'after-save-hook
'(lambda nil
(org-babel-tangle))
nil t)))
'(org-agenda-files '("~/todo.org"))
'(package-selected-packages
'(org-kanban embark-consult embark olivetti vertico-posframe orderless vertico eglot-fsharp consult-eglot eglot nano-modeline mini-modeline pdf-tools consult all-the-icons-completion kind-icon mini-modeline shelldon pcomplete-extension corfu-doc esh-autosuggest fish-completion cape corfu highlight-quoted dirvish ranger magit multi-vterm evil-collection smartparens vterm all-the-icons org-bullets fsharp-mode fish-mode find-file-in-project helpful ahk-mode rainbow-delimiters doom-themes marginalia avy evil-commentary evil-surround undo-tree which-key dashboard))
'(safe-local-variable-values
'((eval add-hook 'after-save-hook
'(lambda nil
(org-babel-tangle))
nil t)))
'(window-divider-mode nil))
(custom-set-faces
;; custom-set-faces was added by Custom.
@ -164,7 +172,7 @@ all of the evil keybindings in buffers like magit, without compromises."
(save-place-mode t)
(setq save-place-file "~/.emacs.vanilla/places")
(setq org-edit-src-content-indentation 0)
(require 'dired)
(require 'dirvish)
(setq delete-by-moving-to-trash t)
@ -311,6 +319,9 @@ all of the evil keybindings in buffers like magit, without compromises."
(org-indent-mode))
(add-hook 'org-mode-hook 'joe/org-mode-setup)
(setq org-todo-keywords '((sequence "TODO" "IN-PROGRESS" "|" "DONE" "BACKLOG")))
(require 'org-tempo)
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(setq org-edit-src-content-indentation 0)
(require 'olivetti)
(setq olivetti-minimum-body-width 120)
@ -441,7 +452,6 @@ all of the evil keybindings in buffers like magit, without compromises."
(all-the-icons-completion-mode)
(add-hook 'marginalia-mode-hook #'all-the-icons-completion-marginalia-setup)
(load-file "~/.emacs.vanilla/elpa/ligature.el/ligature.el")
(require 'ligature)
(global-ligature-mode)
(ligature-set-ligatures 'prog-mode '("|||>" "<|||" "<==>" "<!--" "####" "~~>" "***" "||=" "||>"
@ -467,10 +477,10 @@ all of the evil keybindings in buffers like magit, without compromises."
(require 'lsp)
(require 'consult)
;; (require 'consult-lsp)
(require 'dap-mode)
(require 'dap-netcore)
(require 'dap-gdb-lldb)
(setq dap-print-io t)
;; (require 'dap-mode)
;; (require 'dap-netcore)
;; (require 'dap-gdb-lldb)
;; (setq dap-print-io t)
(require 'eglot)
(require 'eglot-fsharp)
@ -479,17 +489,17 @@ all of the evil keybindings in buffers like magit, without compromises."
(defun joe/compile-run () (interactive) (compile "make run"))
(defun joe/compile-comp () (interactive) (compile "make"))
(require 'tree-sitter)
(require 'tree-sitter-langs)
(require 'evil-textobj-tree-sitter)
(define-key evil-outer-text-objects-map "f" (evil-textobj-tree-sitter-get-textobj "function.outer"))
(define-key evil-inner-text-objects-map "f" (evil-textobj-tree-sitter-get-textobj "function.inner"))
(define-key evil-normal-state-map (kbd "]f") (lambda ()
(interactive)
(evil-textobj-tree-sitter-goto-textobj "function.outer")))
(define-key evil-normal-state-map (kbd "[f") (lambda ()
(interactive)
(evil-textobj-tree-sitter-goto-textobj "function.outer" t)))
;; (require 'tree-sitter)
;; (require 'tree-sitter-langs)
;; (require 'evil-textobj-tree-sitter)
;; (define-key evil-outer-text-objects-map "f" (evil-textobj-tree-sitter-get-textobj "function.outer"))
;; (define-key evil-inner-text-objects-map "f" (evil-textobj-tree-sitter-get-textobj "function.inner"))
;; (define-key evil-normal-state-map (kbd "]f") (lambda ()
;; (interactive)
;; (evil-textobj-tree-sitter-goto-textobj "function.outer")))
;; (define-key evil-normal-state-map (kbd "[f") (lambda ()
;; (interactive)
;; (evil-textobj-tree-sitter-goto-textobj "function.outer" t)))
(setq display-buffer-alist
`((,(rx bos
(| (literal "*compilation")