Increasing the garbage collector threshold should also improve startup time. This increases it from 800 kB to 128MB
#+begin_src emacs-lisp
(setq gc-cons-threshold (* 128 1024 1024))
#+end_src
This resets the threshold back to it's default. This should not be done if =lsp-mode= is enabled, it needs the higher threshold.
#+begin_src emacs-lisp :tangle no
(add-hook 'after-init-hook
(lambda ()
(setq gc-cons-threshold 800000)
(message "gc-cons-threshold restored to %s"
gc-cons-threshold)))
#+end_src
** Increase process output buffer
LSP responses can be rather large, in the 800KiB - 3MiB range. 2MiB is a decent value
#+begin_src emacs-lisp
(setq read-process-output-max (* 2 1024 1024))
#+end_src
** Package sources
Add repositories where packages are installed from. Setting =package-enable-at-startup= to =nil= prevents a second package load and improves startup time
By default packages should always be installed from the package manager. This is equivalent to setting =:ensure t= on each call to =use-package=. To override this for a package (e.g. because it is builtin, or a subpackage), use =:ensure nil=. This is done automatically for packages that use =:load-path=.
#+begin_src emacs-lisp
(setq use-package-always-ensure t)
#+end_src
** Bootstrap straight.el and use-package [DISABLED]
[[https://github.com/radian-software/straight.el][straight.el]] is a pure functional package manager and installs packages from git instead of downloading tars
#+begin_src emacs-lisp :tangle no
(defvar bootstrap-version)
;; Workaround for flycheck. See https://github.com/radian-software/straight.el/issues/508 for more info
Install =use-package= and make it use =straight.el= by default.
#+begin_src emacs-lisp :tangle no
(straight-use-package 'use-package)
(setq straight-use-package-by-default t)
#+end_src
** general.el
[[https://github.com/noctuid/general.el][general.el]] provides a more convenient way for binding keys in emacs. It also integrates with =use-package= with the =:general= keyword.
#+begin_src emacs-lisp
(use-package general
:demand t
:config
(progn
(general-define-key
:prefix my/leader
"a" 'org-agenda
"k" 'general-describe-keybindings)
(general-define-key
"C-M-z" 'zap-to-char
"M-z" 'zap-up-to-char)))
#+end_src
** Setup asdf [DISABLED]
[[https://asdf-vm.com][asdf]] is a tool to install and use multiple versions of development tools and programming languages.
** Set custom settings to load in temp file [DISABLED]
Setting =custom-file= stops emacs from adding customised settings to =init.el=. I prefer to specify everything in this file, so this creates a temporary file where the customisations are stored. This effectively localises customisations to a session
The =customize= functionality is annoying and messes up regularly. Stuff it has done so far:
- Clobber the path to =mix= in Elixir projects
This has been borrowed from [[https://github.com/doomemacs/doomemacs/blob/35865ef5e89442e3809b8095199977053dd4210f/core/core-ui.el#L628-L639][Doom Emacs]]
(lambda (&rest _) (find-config)) nil "" " C-c C "))))
(setq
dashboard-projects-backend 'projectile
dashboard-items '((recents . 5)
(projects . 5)
(registers . 5)))
;; Also show dashboard on new emacsclient window
(setq initial-buffer-choice (lambda ()
(get-buffer-create "*dashboard*")))
:custom-face
(dashboard-heading ((t (:weight bold)))))
#+end_src
** Modeline
[[https://github.com/myrjola/diminish.el][diminish]] hides modes from the modeline
#+begin_src emacs-lisp
(use-package diminish)
#+end_src
[[https://github.com/domtronn/all-the-icons.el][all-the-icons]] provides ALL the icons. Run `all-the-icons-install-fonts` after installing to download the actual font.
#+begin_src emacs-lisp
(use-package all-the-icons
:if (display-graphic-p))
#+end_src
[[https://github.com/tarsius/minions][minions]] adds a menu for minor modes to the modeline
#+begin_src emacs-lisp
(use-package minions
:hook
(doom-modeline-mode . minions-mode))
#+end_src
Use [[https://github.com/seagle0128/doom-modeline][doom-modeline]] for a nice and fancy modeline
=major-mode-hydra= binds a single key to open a context sensitive hydra based on the current major mode. Hydras can be defined in =use-package= definitions via the =:mode-hydra= integration.
#+begin_src emacs-lisp :tangle no
(use-package major-mode-hydra
:bind
("C-M-SPC" . major-mode-hydra)
:config
(major-mode-hydra-define org-mode
()
("Tools"
(("l" org-lint "lint")))))
#+end_src
*** Vertico / Corfu
[[https://github.com/minad/vertico][vertico]] is a minimalistic completion UI based on the default completion system integrated in emacs.
#+begin_src emacs-lisp
(use-package vertico
:custom
(vertico-cycle t)
:init
(vertico-mode))
#+end_src
[[https://github.com/minad/marginalia][marginalia]] adds extra information to the minibuffer completions.
[[https://github.com/minad/consult][consult]] is an alternative to counsel for ivy, but for vertico.
#+begin_src emacs-lisp
(use-package consult
:general
("C-s" 'consult-line)
("C-x c k" 'consult-yank-pop)
:config
(setq consult-project-function (lambda ()
(when (fboundp 'projectile-project-root)
(projectile-project-root)))))
#+end_src
[[https://github.com/minad/corfu][corfu]] enhances the completion at point function popups
#+begin_src emacs-lisp
(use-package corfu
;; :bind
;; ("TAB" . corfu-insert)
:custom
(corfu-cycle t)
(corfu-auto t)
:init
(global-corfu-mode))
#+end_src
[[https://github.com/oantolin/orderless][orderless]] is a flexible completion style that allows flexible matching using literal strings, regex and more.
transient can be used to create command dispatchers. Magit uses it to easily add options to git commands, and it displays a nice popup with the possible flags and commands.
=Flycheck= is a general purpose syntax highlighting framework that provides hooks for other packages and an improvement of the builtin =flymake=.
[[https://www.flycheck.org][website]]
#+begin_src emacs-lisp
(use-package flycheck
:diminish t
:init
(global-flycheck-mode))
#+end_src
*** Tree-sitter
[[https://tree-sitter.github.io/][tree-sitter]] is a new development in parsing and syntax highlighting. There is [[https://www.reddit.com/r/emacs/comments/pxpq8d/rfc_emacs_treesitter_integration/][an effort underway]] to get it into Emacs core, but for now we're using the [[https://emacs-tree-sitter.github.io/][emacs-tree-sitter]] package.
(lsp-completion-provider :none) ;; I'm using corfu
:config
(setq lsp-typescript-surveys-enabled nil
lsp-completion-enable t
lsp-enable-suggest-server-download nil))
#+end_src
[[https://emacs-lsp.github.io/lsp-ui/][lsp-ui]] provides higher level UI elements for =lsp-mode=, like code lenses and flycheck support.
#+begin_src emacs-lisp
(use-package lsp-ui
:ghook 'lsp-mode-hook
:config
(setq lsp-ui-doc-enable t
lsp-ui-peek-enable t
lsp-ui-sideline-enable t
lsp-ui-imenu-enable t)
:custom
(lsp-ui-doc-position 'bottom))
#+end_src
[[https://github.com/emacs-lsp/lsp-ivy][lsp-ivy]] integrates =ivy= into =lsp-mode=
#+begin_src emacs-lisp :tangle no
(use-package lsp-ivy
:commands lsp-ivy-workspace-symbol)
#+end_src
[[https://github.com/gagbo/consult-lsp][consult-lsp]] integrates =consult= into =lsp-mode=
#+begin_src emacs-lisp
(use-package consult-lsp)
#+end_src
[[https://github.com/emacs-lsp/lsp-treemacs][lsp-treemacs]] provides an integration between =lsp-mode= and [[https://github.com/Alexander-Miller/treemacs][treemacs]].
#+begin_src emacs-lisp
(use-package lsp-treemacs
:commands lsp-treemacs-errors-list)
#+end_src
*** DAP
[[http://emacs-lsp.github.io/dap-mode][dap-mode]] provides debugging facilities using the [[https://microsoft.github.io/debug-adapter-protocol/][Debug Adapter Protocol]]
Snippets are predefined pieces of code that can be inserted and filled in. [[https://github.com/joaotavora/yasnippet][YASnippet]] uses syntax inspired by TextMate is the most popular, for good reason.
#+begin_src emacs-lisp
(use-package yasnippet
:diminish t
:general
(:keymaps 'yas-minor-mode-map
"<tab>" nil
"TAB" nil
"<C-tab>" 'yas-expand)
:config
(add-to-list 'yas-snippet-dirs my/snippets-dir)
(yas-global-mode)
:diminish yas-minor-mode)
(use-package yasnippet-snippets)
#+end_src
** Languages
*** JavaScript / TypeScript
Indent 2 spaces
#+begin_src emacs-lisp
(setq-default js-indent-level 2
typescript-indent-level 2)
#+end_src
[[https://github.com/mooz/js2-mode/][js2-mode]] improves a lot on the builtin =js-mode=
Add support for Elixir with [[https://github.com/elixir-editors/emacs-elixir][elixir-mode]]. The =elixir-format= hook sets up the correct formatter configuration when in a =projectile= project.
[[https://github.com/joshwnj/json-mode][json-mode]] extends the builtin =js-mode= with better syntax highlighting for JSON and adds some editing keybindings
Common Lisp does not use =lsp-mode=, but has it's own environment: [[https://github.com/slime/slime][SLIME]] or Superior Lisp Interaction Mode for Emacs.
Similar to =lisp=, there is [[https://github.com/clojure-emacs/cider][CIDER]] (Clojure Interactive Development Environment that Rocks) for Clojure(Script)
#+begin_src emacs-lisp
(use-package cider)
#+end_src
*** Terraform
[[https://github.com/emacsorphanage/terraform-mode][terraform-mode]] is a major mode for Terraform files
#+begin_src emacs-lisp
(use-package terraform-mode
:hook (terraform-mode . lsp-deferred))
#+end_src
*** Fish
[[https://github.com/wwwjfy/emacs-fish][fish-mode]] provides a major mode for fish shell scripts
#+begin_src emacs-lisp
(use-package fish-mode
:init
(setq fish-enable-auto-indent t))
#+end_src
*** Zig
[[https://github.com/ziglang/zig-mode][zig-mode]] provides a major mode for the [[https://ziglang.org][zig programming language]]
=org-datetree= allows you to organise captures by date. It is basically a set of headings representing the date, with the first level for the year, the second level for the month and the third for the day.
#+begin_src emacs-lisp
(use-package org-datetree
;; :straight org
:ensure org
:after org)
#+end_src
=org-protocol= can be used to send data to emacs using =org-protocol://= URLs.
#+begin_src emacs-lisp
(use-package org-protocol
;; :straight org
:ensure org
:after org
:config
(setq org-protocol-default-template-key "c"))
#+end_src
** org-roam
[[https://www.orgroam.com][org-roam]] helps with non-hierarchical note-taking. It uses the [[https://en.wikipedia.org/wiki/Zettelkasten][zettelkasten method]] to capture and organise notes and ideas.
[[https://github.com/org-roam/org-roam-ui][org-roam-ui]] provides a frontend to explore and interact with =org-roam= notes. It can be started with =M-x org-roam-ui-mode RET=, and is then available on [[http://127.0.0.1:35901/]]. Updates are sent real-time through a WebSocket.
The settings provided here are also the defaults, set any to =nil= to disable.
#+begin_src emacs-lisp
(use-package org-roam-ui
:after org-roam
:config
(setq org-roam-ui-sync-theme t
org-roam-ui-follow t
org-roam-ui-update-on-save t
org-roam-ui-open-on-start t))
#+end_src
* Misc
** direnv
[[https://github.com/purcell/envrc][envrc]] adds support for [[https://direnv.net][direnv]] to emacs. =envrc= works on a per-buffer basis, so when you open multiple projects the environments don't pollute eachother. NOTE: this should be loaded last.