- Core Setup & Performance
- Important to load first
- Appearance
- Development
- Version Control
- Completion
- AI
- Other packages
These are essential settings and small tweaks that must load before any packages. They impact the entire configuration, skipping these could result in significantly slower configuration and potential breakage of your setup.
Where to make better:
- Maitanance workspace: Don’t want to see 10 “log” buffers
Neovim setup compared to Emacs: TLDR: Neovim has more developers Marks:
- Emacs setup Better
[] Same
- Emacs setup Worse
[] Lazy.nvim to Elpaca [] Harpoon to Javelin
- blink/Luasnip to Corfu/Cape + Snippy.el
- Autoformat to … (eglot format with evil manual formating) Maybe: format-all
[] Autopairs to Electric-Pair-Mode [] Comment.nvim to comment-line
- Guess indent to …
[] Todo comments to hl-todo [] undotree.nvim to vundo with undo-fu, Undo-fu-session (lacks date support)
- buffer manager to consult-buffer
[] gitsigns to diff-hl
- lazygit to magit
- nvim-lspconfig to eglot
[] mason.nvim to mason.el [] telescope to consult [] lualine to doom-modeline [] gruvbox.nvim to gruvbox.el
- nvim-treesitter to treesit
[] which-key to which-key
The last thing that annoys me about Emacs is there are a lot of useless buffers like: I don’t need these buffers at all:
- Async-native-compile-log
- Native-compile-log
- Compile-log
- Warnings
I also don’t need these but good to have:
- Scratch
- Messages
- Eglot
They are just annoying and make navigation more challenging.
Core performance tweaks moved to early-init.el
Enable lexical-binding
;; -*- lexical-binding: t; -*-Auto-Tangle Org configuration file for better startup times, it refreshes the package-quickstart file. We’ll cover package quickstart in the package manager section later.
If you like to auto tangle an Org file, don’t forget to add the following line to the top of your Org document: (#+PROPERTY: header-args:emacs-lisp :tangle ./init.el :mkdirp yes)
Remember, if this code can’t be loaded (errors before this code), the init.el file won’t update on change! To fix this, you need to find this file (C-x C-f), fix the error and press C-c C-v t to tangle it manually.
(defun start/org-babel-tangle-config ()
"Automatically tangle our init.org config file and refresh package-quickstart when we save it. Credit to Emacs From Scratch for this one!"
(interactive)
(when (string-equal (file-name-directory (buffer-file-name))
(expand-file-name user-emacs-directory))
;; Dynamic scoping to the rescue
(let ((org-confirm-babel-evaluate nil))
(org-babel-tangle)
(package-quickstart-refresh)
)))
(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'start/org-babel-tangle-config)))(defun start/display-startup-time ()
(interactive)
(message "Emacs loaded in %s with %d garbage collections."
(format "%.2f seconds"
(float-time
(time-subtract after-init-time before-init-time)))
gcs-done))
(add-hook 'emacs-startup-hook #'start/display-startup-time)We use the default built in package manager package.el. In my experience Package.el is not slow and gets the job done.
To update/upgrade packages, use the package-upgrade-all command.
A macro that allows you to isolate package configuration in your .emacs file in a way that is both performance-oriented and, well, tidy. We use it because it makes package configuration really easy.
With Emacs 29 use-package is now built-in.
(require 'use-package-ensure) ;; Load use-package-always-ensure
(setq use-package-always-ensure t) ;; Always ensures that a package is installed
;; This only shows which built-in package is upgradable. It does not auto update it
;; TODO: Autoupdate built-in packages. Especially Eglot.
;; (setq package-install-upgrade-built-in t) ;; Update built-in packagesLike Linux distributions, Emacs uses repositories to manage its packages.
(setq package-archives '(("melpa" . "https://melpa.org/packages/") ;; Sets default package repositories
("elpa" . "https://elpa.gnu.org/packages/")
("nongnu" . "https://elpa.nongnu.org/nongnu/"))) ;; For Eat TerminalImproves startup times by allowing Emacs to precompute and generate a single, large autoload file. Instead of re-computing them on every startup.
The larger your configuration, the more it will be felt at startup.
Package quickstart only works with package.el. If you plan to use a different package manager, remember to remove this section and the package-quickstart-refresh line in the Auto-tangle hook.
(setq package-quickstart t) ;; For blazingly fast startup times, this line makes startup miles fasterMakes package installation about 30 sec faster. Also “fixes” multi-vterm not finding vterm (delays vterm module compile).
(use-package async
:defer
:custom
(dired-async-mode t)
(async-bytecomp-package-mode t)
(async-bytecomp-allowed-packages '(all))
(async-package-do-action t))(use-package emacs
:custom
;; Still needed for terminals
(menu-bar-mode nil) ;; Disable the menu bar
(scroll-bar-mode nil) ;; Disable the scroll bar
(tool-bar-mode nil) ;; Disable the tool bar
(inhibit-startup-screen t) ;; Disable welcome screen
(delete-selection-mode t) ;; Select text and delete it by typing.
(electric-indent-mode nil) ;; Turn off the weird indenting that Emacs does by default.
(electric-pair-mode t) ;; Turns on automatic parens pairing
(blink-cursor-mode nil) ;; Don't blink cursor
(global-auto-revert-mode t) ;; Automatically reload file and show changes if the file has changed
(use-short-answers t) ;; Since Emacs 29, `yes-or-no-p' will use `y-or-n-p'
(dired-kill-when-opening-new-dired-buffer t) ;; Dired don't create new buffer
(recentf-mode t) ;; Enable recent file mode
(context-menu-mode t) ;; Right-click menu
;; (global-visual-line-mode t) ;; Enable line wrapping
(truncate-lines t) ;; Enable long lines
(display-line-numbers-type 'relative) ;; Relative line numbers
(global-display-line-numbers-mode t) ;; Display line numbers
(global-hl-line-mode t) ;; Highlight current line
;; (pixel-scroll-precision-mode t) ;; Precise pixel scrolling. i.e. smooth scrolling
;; (pixel-scroll-precision-use-momentum nil)
(native-comp-async-report-warnings-errors 'silent) ;; Don't show native comp errors
(warning-minimum-level :error) ;; Only show errors in warnings buffer
(mouse-wheel-progressive-speed nil) ;; Disable progressive speed when scrolling
(scroll-conservatively 10) ;; Smooth scrolling
(scroll-margin 8)
(indent-tabs-mode nil) ;; Only use spaces for indentation
(tab-width 4)
(sgml-basic-offset 4) ;; Set Html mode indentation to 4
(c-ts-mode-indent-offset 4) ;; Fix weird indentation in c-ts (C, C++)
(go-ts-mode-indent-offset 4) ;; Fix weird indentation in go-ts
(display-fill-column-indicator-column 80) ;; Set line length indicator to 80 characters
(whitespace-style '(face tabs tab-mark trailing))
(make-backup-files nil) ;; Stop creating ~ backup files
(auto-save-default nil) ;; Stop creating # auto save files
(delete-by-moving-to-trash t)
:hook
(prog-mode . hs-minor-mode) ;; Enable folding hide/show globally
(prog-mode . display-fill-column-indicator-mode) ;; Display line length indicator
(prog-mode . whitespace-mode)
:config
;; Move customization variables to a separate file and load it, avoid filling up init.el with unnecessary variables
(setq custom-file (locate-user-emacs-file "custom-vars.el"))
(load custom-file 'noerror 'nomessage)
:bind (
([escape] . keyboard-escape-quit) ;; Makes Escape quit prompts (Minibuffer Escape)
;; Zooming In/Out
("C-+" . text-scale-increase)
("C--" . text-scale-decrease)
("<C-wheel-up>" . text-scale-increase)
("<C-wheel-down>" . text-scale-decrease)
))Packages that we want to load first so we have them as soon as possible if something breaks.
An extensible vi/vim layer for Emacs.
Notes:
- You can toggle evil mode with C-z.
- To paste without yank select the text and use P. This line is especially for ThePrimeagen :)
(use-package evil
:hook (after-init . evil-mode)
:config
(evil-set-initial-state 'eat-mode 'insert) ;; Set initial state in eat terminal to insert mode
(global-set-key [C-backspace] 'evil-delete-backward-word) ;; Make C-backspace less agressive
:custom
(evil-want-keybinding nil) ;; Disable evil bindings in other modes (It's not consistent and not good)
(evil-want-C-u-scroll t) ;; Set C-u to scroll up
(evil-want-C-i-jump nil) ;; Disables C-i jump
(evil-undo-system 'undo-fu) ;; C-r to redo
(evil-want-fine-undo t)
(evil-respect-visual-line-mode t)
;; Unmap keys in 'evil-maps. If not done, org-return-follows-link will not work
:bind
(:map evil-motion-state-map
("SPC" . nil)
("RET" . nil)
("TAB" . nil)))
(use-package evil-collection
:after evil
:config
;; Setting where to use evil-collection
(setq evil-collection-mode-list '(dired ibuffer magit corfu consult info vterm vundo (package-menu package) bookmark))
(evil-collection-init))A keybinding framework to set keybindings easily.
We use general because it gives:
- a convenient method for binding keys.
- easy leader key integration.
- good evil-mode and which-key support.
- a consistent and unified interface for managing keybinds.
And it is also really customizable.
Performance and startup time is about the same when lazy loaded. Much more convenient to use:
- Like :keymaps ‘override
- Which key macro
(defun mark/open-init-file ()
"Open init.org configuration file"
(interactive)
(find-file "~/.config/emacs/init.org"))
(defun mark/reload-config()
"Reload Emacs config"
(interactive)
(load-file "~/.config/emacs/init.el"))
(use-package general
:after (evil)
:config
(general-evil-setup) ;; <- evil
;; Set up 'C-SPC' as the leader key
(general-create-definer start/leader-keys
:states '(normal insert visual motion emacs) ;; <- evil
:keymaps 'override
:prefix "SPC"
:global-prefix "C-SPC") ;; Set global leader key so we can access our keybindings from any state
(start/leader-keys
"." '(find-file :wk "Find file")
"," '(embark-act :wk "Embark act")
"TAB" '(comment-line :wk "Comment lines")
"q" '(flymake-show-buffer-diagnostics :wk "Flymake buffer diagnostic")
"u" '(vundo :wk "Vundo")
;; Projectile
"p" '(projectile-command-map :wk "Projectile")
"s p" '(projectile-discover-projects-in-search-path :wk "Search for projects"))
(start/leader-keys
"m" '(:ignore t :wk "Bookmarks & Registers")
;; Registers
"m s" '(consult-register :wk "Consult register")
"m k" '(jump-to-register :wk "Jump to register")
"m e" '(point-to-register :wk "Point to register")
;; Bookmarks
"m a" '(bookmark-set :wk "Bookmark Set")
"m d" '(bookmark-jump :wk "Bookmark Jump")
"m r" '(bookmark-delete :wk "Bookmark Delete")
"m R" '(bookmark-delete-all :wk "Bookmark Delete All")
"m l" '(bookmark-bmenu-list :wk "Bookmark bmenu list")
"m c" '(consult-bookmark :wk "Consult Bookmark"))
;; Javelin (Harpoon)
(start/leader-keys
"a" '(javelin-toggle-quick-menu :wk "Javelin quick menu")
"j" '(:ignore t :wk "Javelin")
"j a" '(javelin-add-file :wk "Javelin add file")
"j d" '(javelin-delete :wk "Javelin Delete")
"j c" '(javelin-clear :wk "Javelin clear")
"j C" '(javelin-clear-all :wk "Javelin clear all")
"j p" '(javelin-go-to-prev :wk "Javelin previous")
"j n" '(javelin-go-to-next :wk "Javelin next"))
(start/leader-keys
"s" '(:ignore t :wk "Search")
"s c" '(mark/open-init-file :wk "Open init file")
"s r" '(consult-recent-file :wk "Search recent files")
"s f" '(consult-fd :wk "Search files with fd")
"s g" '(consult-ripgrep :wk "Search with ripgrep")
"s l" '(consult-line :wk "Search line")
"s i" '(consult-imenu :wk "Search Imenu buffer locations") ;; This one is really cool
"s e" '(sudo-edit :wk "Sudo edit current file")
"s u" '(sudo-edit-find-file :wk "Sudo edit find file")
"s o" '(jinx-correct :wk "Jinx correct")
"s x" '(jinx-languages :wk "Jinx choose language"))
(start/leader-keys
"d" '(:ignore t :wk "Buffers & Dired")
"d s" '(consult-buffer :wk "Switch buffer")
"d k" '(kill-current-buffer :wk "Kill current buffer")
"d i" '(ibuffer :wk "Ibuffer")
"d n" '(next-buffer :wk "Next buffer")
"d p" '(previous-buffer :wk "Previous buffer")
"d r" '(revert-buffer :wk "Reload buffer")
"d v" '(dired :wk "Open dired")
"d j" '(dired-jump :wk "Dired jump to current")
"d a" '(consult-dir :wk "Consult dir"))
(start/leader-keys
"e" '(:ignore t :wk "Languages")
"e e" '(eglot-reconnect :wk "Eglot Reconnect")
"e d" '(eldoc-doc-buffer :wk "Eldoc Buffer")
"e f" '(eglot-format :wk "Eglot Format")
"e l" '(consult-flymake :wk "Consult Flymake")
"e n" '(flymake-goto-next-error :wk "Flymake next error")
"e p" '(flymake-goto-prev-error :wk "Flymake previous error")
"e a" '(eglot-code-actions :wk "Eglot code actions")
"e r" '(eglot-rename :wk "Eglot Rename")
"e i" '(xref-find-definitions :wk "Find definition")
"e s" '(xref-find-references :wk "Find references")
"e v" '(:ignore t :wk "Elisp")
"e v b" '(eval-buffer :wk "Evaluate elisp in buffer")
"e v r" '(eval-region :wk "Evaluate elisp in region"))
(start/leader-keys
"g" '(:ignore t :wk "Git")
"g s" '(magit-status :wk "Magit status"))
(start/leader-keys
"r" '(:ignore t :wk "Reload & Packages") ;; To get more help use C-h commands (describe variable, function, etc.)
;; Mason.el
"r m" '(mason-manager :wk "Mason manager")
"r i" '(mason-install :wk "Mason install")
;; Package-menu-mode
"r p" '(list-packages :wk "List packages")
"r c" '(package-menu-clear-filter :wk "Package clear filters")
"r n" '(package-menu-filter-by-name :wk "Package filter by name")
"r N" '(package-menu-filter-by-name-or-description :wk "Package filter by name or descriptions")
"r s" '(package-menu-filter-by-status :wk "Package filter by status")
"r u" '(package-menu-filter-upgradable :wk "Package filter by upgradable")
"r q" '(save-buffers-kill-emacs :wk "Quit Emacs and Daemon")
"r r" '(mark/reload-config :wk "Reload Emacs config"))
(start/leader-keys
"v" '(:ignore t :wk "Vterm")
"v m" '(multi-vterm :wk "New multi-vterm")
"v n" '(multi-vterm-next :wk "Multi vterm next")
"v p" '(multi-vterm-prev :wk "Multi vterm prev")
"v d" '(multi-vterm-dedicated-toggle :wk "Toggle multi-vterm dedicated"))
(start/leader-keys
"l" '(:ignore t :wk "LLM")
"l a" '(gptel :wk "Launch Gptel")
"l m" '(gptel-menu :wk "Gptel Menu")
"l s" '(gptel-send :wk "Gptel send")
"l d" '(gptel-add :wk "Gptel add region")
"l f" '(gptel-add-file :wk "Gptel add file")
"l r" '(gptel-rewrite :wk "Gptel rewrite")
"l c" '(gptel-abort :wk "Cancel prompt"))
(start/leader-keys
"t" '(:ignore t :wk "Toggle")
"t t" '(visual-line-mode :wk "Toggle truncated lines (wrap)")
"t l" '(display-line-numbers-mode :wk "Toggle line numbers")
"t j" '(jinx-mode :wk "Toggle Jinx Spell Checker")
"t m" '(evil-mc-mode :wk "Toggle Evil mc mode"))
)
;; Fix general.el leader key not working instantly in messages buffer with evil mode
(use-package emacs
:after (evil general)
:ghook ('after-init-hook
(lambda (&rest _)
(when-let ((messages-buffer (get-buffer "*Messages*")))
(with-current-buffer messages-buffer
(evil-normalize-keymaps))))
nil nil t))Vundo: Visualizes undo history. Undo-fu-session: Persistent undo history
(use-package undo-fu
:config
;; Increase undo history limits to reduce likelihood of data loss
(setq undo-limit (* 1024 1024 64) ;; 64mb (default is 160kb)
undo-strong-limit (* 1024 1024 96) ;; 96mb (default is 240kb)
undo-outer-limit (* 1024 1024 960))) ;; 960mb (default is 24mb)
(use-package undo-fu-session
:hook (after-init . undo-fu-session-global-mode)
:custom (undo-fu-session-incompatible-files '("\\.gpg$" "/COMMIT_EDITMSG\\'" "/git-rebase-todo\\'"))
:config
(when (executable-find "zstd")
;; There are other algorithms available, but zstd is the fastest, and speed
;; is our priority within Emacs
(setq undo-fu-session-compression 'zst)))
(use-package vundo
:defer
:custom
(vundo-glyph-alist vundo-unicode-symbols)
(vundo-compact-display t))Set gruvbox theme, if you want some themes try out doom-themes. Use consult-theme to easily try out themes (Epilepsy Warning).
(use-package doom-themes
:custom
;; Global settings (defaults)
(doom-themes-enable-bold t) ; if nil, bold is universally disabled
(doom-themes-enable-italic t) ; if nil, italics is universally disabled
:config
(load-theme 'doom-gruvbox t)
;; Corrects (and improves) org-mode's native fontification.
(doom-themes-org-config))With Emacs version 29, true transparency has been added.
(add-to-list 'default-frame-alist '(alpha-background . 90)) ;; For all new frames henceforth
;; Transparency in terminal
(defun start/tui-enable-transparency ()
(unless (display-graphic-p (selected-frame))
(set-face-background 'default "unspecified-bg" (selected-frame))))
(add-hook 'window-setup-hook 'start/tui-enable-transparency)A fancy, fast and customizable mode-line.
(use-package doom-modeline
:custom
(doom-modeline-height 25) ;; Set modeline height
:hook (after-init . doom-modeline-mode))This is an icon set that can be used with dired, ibuffer and other Emacs packages. Don’t forget nerd-icons-install-fonts to install the resource fonts.
We use nerd-icons because it supports both GUI and TUI unlike all-the-icons. Also Doom modeline requires nerd icons.
(use-package nerd-icons :defer)
(use-package nerd-icons-dired
:hook (dired-mode . nerd-icons-dired-mode))
(use-package nerd-icons-ibuffer
:hook (ibuffer-mode . nerd-icons-ibuffer-mode))Project interaction library for Emacs.
Emacs has a built in project manager called project.el, but we don’t use it. You can try it out with the keybinds under C-x p because project.el does not require any special setup to use.
We use projectile because it:
- supports more features and project types.
- has better integration with projects.
- has better documentation.
- is developed faster.
More reasons to use projectile.
(use-package projectile
:hook (after-init . projectile-mode)
:custom
(projectile-auto-discover nil) ;; Disable auto search for better startup times ;; Search with a keybind
(projectile-run-use-comint-mode t) ;; Interactive run dialog when running projects inside emacs (like giving input)
(projectile-switch-project-action #'projectile-dired) ;; Open dired when switching to a project
(projectile-project-search-path '(("/mnt/Ext4D/Mark/Projektek/" . 2)
("/mnt/Ext4D/Mark/Projektek/Desktop/Gyakorlas/" . 2)
("/mnt/Ext4D/Mark/Projektek/Desktop/Iskola/" . 3)
)))(use-package consult-dir
:defer
:custom
(consult-dir-default-command #'consult-dir-dired)
:config
;; A function that returns a list of directories
(defun consult-dir--work-dirs ()
"Return list of work dirs."
(append
(split-string (shell-command-to-string "find ~/.config -maxdepth 1 -type d") "\n" t)
(split-string (shell-command-to-string "find /mnt/Ext4D/Mark/Projektek/ /mnt/Ext4D/Mark/Projektek/Desktop/Gyakorlas/ /mnt/Ext4D/Mark/Projektek/Desktop/Iskola/ -mindepth 2 -maxdepth 2 -type d") "\n" t)
))
;; A consult source that calls this function
(defvar consult-dir--source-work
`(:name "Work Directories"
:narrow ?w
:category file
:face consult-file
:history file-name-history
:enabled ,(lambda () (executable-find "find"))
:items ,#'consult-dir--work-dirs)
"Work directory source for `consult-dir'.")
;; Adding to the list of consult-dir sources
(add-to-list 'consult-dir-sources 'consult-dir--source-work t))Modern, better maintained version of harpoon.el
(use-package javelin
:hook (after-init . global-javelin-minor-mode))Built in Emacs client for the Language Server Protocol. We use Eglot because it is fast and minimal. For more: C-h i: g: (eglot)Top
Eglot does not automatically download LSP servers. It requires separate download. The easiest way to install LSP servers is with a package manager.
If you can’t use a package manager you can do the following:
- Download the server (e.g. from github)
- Add the binary/executable to your path.
- Or customize the eglot-server-programs list.
To control how a LSP server is started customize the eglot-server-programs list.
(use-package eglot
:ensure nil ;; Don't install eglot because it's now built-in
:hook ((c-ts-mode c++-ts-mode
csharp-mode java-ts-mode
html-ts-mode css-ts-mode
js-ts-mode typescript-ts-mode
php-ts-mode cmake-ts-mode
go-ts-mode rust-ts-mode
haskell-mode bash-ts-mode
gdscript-ts-mode glsl-mode
hyprlang-ts-mode)
. eglot-ensure)
:custom
;; Good default
(eglot-events-buffer-size 0) ;; No event buffers (LSP server logs)
(eglot-autoshutdown t);; Shutdown unused servers.
(eglot-report-progress nil) ;; Disable LSP server logs (Don't show lsp messages at the bottom, java)
;; Manual lsp servers
:config
(add-to-list 'eglot-server-programs
`(hyprlang-ts-mode . ("hyprls" "-lsp")))
(add-to-list 'eglot-server-programs
`(vue-ts-mode . ("vue-language-server" "-lsp")))
)Package manager for LSP, DAP, linters, and more for the Emacs Operating System. I waited so long for a package like this.
(use-package mason
:hook (after-init . mason-ensure))Show flymake errors with sideline
(use-package sideline-flymake
:hook (flymake-mode . sideline-mode)
:custom
(sideline-flymake-display-mode 'line) ;; show errors on the current line
(sideline-backends-right '(sideline-flymake)))A template system for Emacs. And yasnippet-snippets is a snippet collection package. To use it write out the full keyword (or use autocompletion) and press Tab.
(use-package yasnippet-snippets
:hook (prog-mode . yas-minor-mode))
(defun mark/corfu-yas-tab-handler ()
"Prioritize corfu over yasnippet when yasnippet is active"
(interactive)
;; There is no direct way to get if corfu is currently displayed so we watch the completion index
(if (> corfu--index -1)
(corfu-complete)
(yas-next-field-or-maybe-expand)
))
(use-package emacs
:after (yasnippet corfu)
:bind
(:map yas-keymap
("TAB" . mark/corfu-yas-tab-handler)))VSCode/LSP snippet support for Emacs with Yasnippet.
(use-package snippy
:vc (:url "https://github.com/MiniApollo/snippy.git"
:branch "main"
:rev :newest)
:hook (after-init . global-snippy-minor-mode)
:custom
(snippy-global-languages '("global")) ;; Recomended
:config
(snippy-install-or-update-snippets)) ;; Autoupdate git repoA parser generator tool and an incremental parsing library. Check out TJ’s video to learn why you should use it.
With Emacs 29 Tree-Sitter is now built-in. You may need to compile Emacs from source to have it enabled. You also need to have a compiler installed so Emacs can compile the parsers into a shared library. For more info about how to use Tree-Sitter check out this masteringemacs article.
Using Tree-Sitter is somewhat hacky because it requires you to:
- manually manage a source list of the parsers you want to use.
- remap the major modes you want to use.
You can also use treesit-auto, but it is updated quite slowly so we don’t use it.
To use it, remove :tangle no from the beginning of the source code block.
(setq treesit-language-source-alist
'((bash "https://github.com/tree-sitter/tree-sitter-bash")
(cmake "https://github.com/uyha/tree-sitter-cmake")
(c "https://github.com/tree-sitter/tree-sitter-c")
(cpp "https://github.com/tree-sitter/tree-sitter-cpp")
(css "https://github.com/tree-sitter/tree-sitter-css")
(elisp "https://github.com/Wilfred/tree-sitter-elisp")
(gdscript "https://github.com/PrestonKnopp/tree-sitter-gdscript")
(go "https://github.com/tree-sitter/tree-sitter-go")
(gomod "https://github.com/camdencheek/tree-sitter-go-mod")
(html "https://github.com/tree-sitter/tree-sitter-html")
(hyprlang "https://github.com/tree-sitter-grammars/tree-sitter-hyprlang")
(java "https://github.com/tree-sitter/tree-sitter-java")
(javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src")
(json "https://github.com/tree-sitter/tree-sitter-json")
(make "https://github.com/alemuller/tree-sitter-make")
(python "https://github.com/tree-sitter/tree-sitter-python")
(rust "https://github.com/tree-sitter/tree-sitter-rust")
(toml "https://github.com/tree-sitter/tree-sitter-toml")
(tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src")
(typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src")
(vue "https://github.com/ikatyang/tree-sitter-vue")
(yaml "https://github.com/ikatyang/tree-sitter-yaml")))
(defun start/install-treesit-grammars ()
"Install missing treesitter grammars"
(interactive)
(dolist (grammar treesit-language-source-alist)
(let ((lang (car grammar)))
(unless (treesit-language-available-p lang)
(treesit-install-language-grammar lang)))))
;; Call this function to install missing grammars
(add-hook 'after-init-hook #'start/install-treesit-grammars)
;; Optionally, add any additional mode remappings not covered by defaults
(setq major-mode-remap-alist
'((yaml-mode . yaml-ts-mode)
(sh-mode . bash-ts-mode)
(c-mode . c-ts-mode)
(c++-mode . c++-ts-mode)
(css-mode . css-ts-mode)
(python-mode . python-ts-mode)
(mhtml-mode . html-ts-mode)
(java-mode . java-ts-mode)
(javascript-mode . js-ts-mode)
(js-json-mode . json-ts-mode)
(typescript-mode . typescript-ts-mode)
(conf-toml-mode . toml-ts-mode)
(gdscript-mode . gdscript-ts-mode)
))
(setq treesit-font-lock-level 3)
;; Or if there is no built in mode
(use-package cmake-ts-mode :ensure nil :mode ("CMakeLists\\.txt\\'" "\\.cmake\\'"))
(use-package go-mod-ts-mode :ensure nil :mode "\\.mod\\'")
(use-package lua-ts-mode :ensure nil :mode "\\.lua\\'")
(use-package rust-ts-mode :ensure nil :mode "\\.rs\\'")
(use-package typescript-ts-mode :ensure nil :mode "\\.ts\\'")
(use-package tsx-ts-mode :ensure nil :mode "\\.tsx\\'")
(use-package yaml-ts-mode :ensure nil :mode ("\\.yaml\\'" "\\.yml\\'"))
(use-package hyprlang-ts-mode
:mode ("/hypr/.*\\.conf\\'")
:custom
(hyprlang-ts-mode-indent-offset 4))
(use-package markdown-ts-mode
:mode ("\\.md\\'")
:config
(add-to-list 'treesit-language-source-alist '(markdown "https://github.com/tree-sitter-grammars/tree-sitter-markdown" "split_parser" "tree-sitter-markdown/src"))
(add-to-list 'treesit-language-source-alist '(markdown-inline "https://github.com/tree-sitter-grammars/tree-sitter-markdown" "split_parser" "tree-sitter-markdown-inline/src")))
;; (use-package vue-ts-mode
;; :vc (:url "https://github.com/8uff3r/vue-ts-mode.git"
;; :branch "main")
;; :mode "\\.vue\\'");; https://www.reddit.com/r/emacs/comments/1c5dkup/how_to_modify_syntax_highlighting_in_treesitter/
;; https://github.com/emacs-mirror/emacs/blob/master/admin/notes/tree-sitter/starter-guide
(use-package go-ts-mode
:ensure nil
:mode "\\.go\\'"
:config
(defvar mark/ts-font-lock-settings
(treesit-font-lock-rules
:language 'go ;; What language
:feature 'function-highlight ;; A unique feature name that we can toggle.
`(
;; Function calls
(call_expression
function: (selector_expression
field: (field_identifier) @font-lock-function-call-face)) ;; Use 'describe-face' to find faces
;; Property values
(argument_list
(selector_expression
field: (field_identifier) @font-lock-property-use-face))
(expression_list
(selector_expression
field: (field_identifier) @font-lock-property-use-face))
;; ((Treesit patern) @defface_Settings)
))
"Go-ts-mode settings, fix not highlighting function calls and property values")
(add-hook 'go-ts-mode-hook
(lambda () (setq-local treesit-font-lock-settings
(append treesit-font-lock-settings
mark/ts-font-lock-settings))))
)Emmet’s support for emacs.
(use-package emmet-mode
:hook
((sgml-mode css-base-mode) . emmet-mode) ;; Auto-start on any markup modes
:config
(sgml-electric-tag-pair-mode)) ;; Auto close tagsEmacs contains many “editing modes” that alter its basic behavior in useful ways. These are divided into “major modes” and “minor modes”. For more: C-h i: g: (emacs)Modes
Some programming languages require the installation of specific modes to fully integrate and function within Emacs. These packages are often necessary for features like syntax highlighting, code formatting, linting, and language-specific features.
(use-package haskell-mode
:mode "\\.hs\\'")An Emacs package to get GDScript support and syntax highlighting.
(use-package gdscript-mode
:mode "\\.gd\\'")One of the things that Emacs is loved for. Once you’ve used it for a bit, you’ll understand why people love it. Even reading about it can be inspiring! For example, this document is effectively the source code and descriptions bound into the one document, much like the literate programming ideas that Donald Knuth made famous.
We use an Org mode document for our Emacs configuration because it provides:
- Better organization: It lets us structure with outlines, headings, and tags.
- Literate Documentation: It’s a document, not just source code.
- Fast Navigation: Quickly jump to sections with something like Imenu.
For templates use C-c C-, Much easier than org-tempo
(use-package org
:ensure nil
:custom
(org-edit-src-content-indentation 4) ;; Set src block automatic indent to 4 instead of 2.
(org-return-follows-link t) ;; Sets RETURN key in org-mode to follow links
:hook
(org-mode . org-indent-mode) ;; Indent text
)(use-package toc-org
:commands toc-org-enable
:hook (org-mode . toc-org-mode))Prettify headings and plain lists in Org mode. Modern version of org-bullets.
(use-package org-superstar
:after org
:hook (org-mode . org-superstar-mode))Fully-fledged terminal emulator inside GNU Emacs. Fast, POSIX compliant shell, handles UIs well.
(use-package vterm
:defer
:hook (vterm-mode . (lambda () (setq-local global-hl-line-mode nil)))
:custom
(vterm-max-scrollback 5000)
(vterm-always-compile-module t))Managing multiple vterm buffers in Emacs
(use-package multi-vterm
:after vterm)(use-package exec-path-from-shell
:hook (after-init . exec-path-from-shell-initialize))Complete text-based user interface to Git.
(use-package transient
:defer
:config
(define-key transient-map (kbd "<escape>") 'transient-quit-one)) ;; Make escape quit magit prompts
(use-package magit
:defer
:custom (magit-diff-refine-hunk (quote all)) ;; Shows inline diff
:config
(setopt magit-format-file-function #'magit-format-file-nerd-icons) ;; Magit nerd icons
)Highlights uncommitted changes on the left side of the window (area also known as the “gutter”), allows you to jump between and revert them selectively.
(use-package diff-hl
:hook ((dired-mode . diff-hl-dired-mode-unless-remote)
(magit-post-refresh . diff-hl-magit-post-refresh)
(after-init . global-diff-hl-mode)))Enhances in-buffer completion with a small completion popup. Corfu is a small package, which relies on the Emacs completion facilities and concentrates on providing a polished completion. For more configuration options check out their git repository. Notes:
- To enter Orderless field separator, use M-SPC.
(use-package corfu
;; Optional customizations
:custom
(corfu-cycle t) ;; Enable cycling for `corfu-next/previous'
(corfu-auto t) ;; Enable auto completion
(corfu-auto-prefix 2) ;; Minimum length of prefix for auto completion.
(corfu-popupinfo-mode t) ;; Enable popup information
(corfu-popupinfo-delay 0.5) ;; Lower popup info delay to 0.5 seconds from 2 seconds
(corfu-separator ?\s) ;; Orderless field separator, Use M-SPC to enter separator
(completion-ignore-case t)
;; Emacs 30 and newer: Disable Ispell completion function.
;; Try `cape-dict' as an alternative.
(text-mode-ispell-word-completion nil)
;; Enable indentation+completion using the TAB key.
;; `completion-at-point' is often bound to M-TAB.
(tab-always-indent 'complete)
(corfu-preview-current nil) ;; Don't insert completion without confirmation
;; Recommended: Enable Corfu globally. This is recommended since Dabbrev can
;; be used globally (M-/). See also the customization variable
;; `global-corfu-modes' to exclude certain modes.
:hook (after-init . global-corfu-mode))
(use-package nerd-icons-corfu
:after corfu
:init (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))Provides Completion At Point Extensions which can be used in combination with Corfu, Company or the default completion UI. Notes:
- The functions that are added later will be the first in the completion list.
- Be aware when adding Capfs (Completion-at-point-functions) to the list since each of the Capfs adds a small runtime cost.
Read the configuration section in Cape’s readme for more information.
(use-package yasnippet-capf :defer)
(defun mark/setup-capfs ()
"Configure completion backends"
;; Take care when adding Capfs to the list since each of the Capfs adds a small runtime cost.
(let ((merge-backends (list
#'cape-keyword ;; Keyword completion
;; #'cape-abbrev ;; Complete abbreviation
#'cape-dabbrev ;; Complete word from current buffers
;; #'cape-line ;; Complete entire line from current buffer
;; #'cape-history ;; Complete from Eshell, Comint or minibuffer history
;; #'cape-dict ;; Dictionary completion (Needs Dictionary file installed)
;; #'cape-tex ;; Complete Unicode char from TeX command, e.g. \hbar
;; #'cape-sgml ;; Complete Unicode char from SGML entity, e.g., &alpha
;; #'cape-rfc1345 ;; Complete Unicode char using RFC 1345 mnemonics
#'snippy-capf ;; Vscode Snippets
#'yasnippet-capf ;; Yasnippet snippets
))
(seperate-backends (list
#'cape-file ;; Path completion
#'cape-elisp-block ;; Complete elisp in Org or Markdown mode
)))
;; Remove keyword completion in git commits
(when (derived-mode-p 'git-commit-mode)
(setq merge-backends (remq #'cape-keyword merge-backends)))
;; Add Elisp symbols only in Elisp modes
(when (derived-mode-p 'emacs-lisp-mode 'ielm-mode)
(setq merge-backends (cons #'cape-elisp-symbol merge-backends))) ;; Emacs Lisp code (functions, variables)
;; Add Eglot to the front of the list if it's active
(when (bound-and-true-p eglot--managed-mode)
(setq merge-backends (cons #'eglot-completion-at-point merge-backends)))
;; Create the super-capf and set it buffer-locally
(setq-local completion-at-point-functions
(append
seperate-backends
(list (apply #'cape-capf-super merge-backends)))
)))
(use-package cape
:after (corfu)
:init
;; Add to the global default value of `completion-at-point-functions' which is
;; used by `completion-at-point'. The order of the functions matters, the
;; first function returning a result wins. Note that the list of buffer-local
;; completion functions takes precedence over the global list.
;; Seperate function needed, because we use setq-local (everything is replaced)
(add-hook 'eglot-managed-mode-hook #'mark/setup-capfs)
(add-hook 'prog-mode-hook #'mark/setup-capfs)
(add-hook 'text-mode-hook #'mark/setup-capfs))Completion style that divides the pattern into space-separated components and matches candidates that match all of the components in any order. Recommended for packages like vertico, corfu.
(use-package orderless
:defer
:custom
(completion-styles '(orderless basic))
(completion-category-overrides '((file (styles basic partial-completion)))))- Vertico: Provides a performant and minimalistic vertical completion UI based on the default completion system.
- Savehist: Saves completion history.
- Marginalia: Adds extra metadata for completions in the margins (like descriptions).
- Nerd-icons-completion: Adds icons to completion candidates using the built in completion metadata functions.
We use these packages because they use Emacs native functions. Unlike Ivy or Helm.
(use-package vertico
:hook (after-init . vertico-mode)
:bind (:map vertico-map
("C-j" . vertico-next)
("C-k" . vertico-previous)
("C-u" . vertico-scroll-down)
("C-d" . vertico-scroll-up))
:custom
(vertico-cycle t) ;; Enable cycling for `vertico-next/previous'
)
(savehist-mode) ;; Enables save history mode
(use-package marginalia
:after vertico
:config
(marginalia-mode))
(use-package nerd-icons-completion
:after marginalia
:config
(nerd-icons-completion-mode)
:hook
(marginalia-mode . nerd-icons-completion-marginalia-setup))Emacs Mini-Buffer Actions Rooted in Keymaps
(use-package embark :defer)
(use-package embark-consult
:hook
(embark-collect-mode . consult-preview-at-point-mode))Enchanted Spell Checker Jinx can cause performance problems in large markdown files.
(use-package jinx
:hook (after-init . global-jinx-mode))A simple, extensible LLM client for Emacs
(use-package gptel
:defer
:custom
(gptel-default-mode 'org-mode)
(gptel-post-response-functions #'gptel-end-of-response)
:config
(require 'gptel-integrations)
(setq gptel--known-backends nil) ;; Remove chatgpt backend
;; OPTIONAL configuration
(setq
gptel-model 'functiongemma:latest
gptel-model 'qwen3:8b
gptel-backend (gptel-make-ollama "Ollama"
:host "localhost:11434"
:stream t
:models '((qwen3:8b
:description "Qwen3 with 8b")
(functiongemma:latest
:description "Specialized Gemma3, fine-tuned for function calling")
))
))An Mcp client inside Emacs
(use-package mcp
:after gptel
:custom (mcp-hub-servers
`(
("my-test-server" . (
:command "uv"
:args ("run" "--with" "mcp" "/home/mark/Downloads/mcpTest/server.py")))
("duckduckgo-mcp" . (
:command "uvx"
:args ("duckduckgo-mcp-server")))
("Fetch-mcp" . (
:command "uvx"
:args ("mcp-server-fetch")))
))
:config
(require 'mcp-hub)
(gptel-mcp-connect nil))All the package setups that don’t need much tweaking.
Provides search and navigation commands based on the Emacs completion function. Check out their git repository for more awesome functions.
(use-package consult
;; Enable automatic preview at point in the *Completions* buffer. This is
;; relevant when you use the default completion UI.
:hook (completion-list-mode . consult-preview-at-point-mode)
:init
;; Optionally configure the register formatting. This improves the register
;; preview for `consult-register', `consult-register-load',
;; `consult-register-store' and the Emacs built-ins.
(setq register-preview-delay 0.5
register-preview-function #'consult-register-format)
;; Optionally tweak the register preview window.
;; This adds thin lines, sorting and hides the mode line of the window.
(advice-add #'register-preview :override #'consult-register-window)
;; Use Consult to select xref locations with preview
(setq xref-show-xrefs-function #'consult-xref
xref-show-definitions-function #'consult-xref)
:config
;;;; 4. projectile.el (projectile-project-root)
(autoload 'projectile-project-root "projectile")
(setq consult-project-function (lambda (_) (projectile-project-root)))
)Utilities for opening files with root privileges (also works with doas).
(use-package sudo-edit
:defer
:custom (sudo-edit-local-method "doas")) ;; To use doasMultiple-cursors for evil mode.
(use-package evil-mc :defer)An alternative to the built-in Emacs help that provides much more contextual information.
(use-package helpful
:bind
;; Note that the built-in `describe-function' includes both functions
;; and macros. `helpful-function' is functions only, so we provide
;; `helpful-callable' as a drop-in replacement.
("C-h f" . helpful-callable)
("C-h v" . helpful-variable)
("C-h k" . helpful-key)
("C-h x" . helpful-command))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 :defer)Adds colors to brackets.
(use-package rainbow-delimiters
:hook (prog-mode . rainbow-delimiters-mode))Display the actual color as a background for any hex color value (ex. #ffffff).
(use-package rainbow-mode
:diminish
:hook
((org-mode prog-mode) . rainbow-mode))Highlight TODO keywords
(use-package hl-todo
:hook
((prog-mode yaml-ts-mode) . hl-todo-mode)
:config
;; From doom emacs
(setq hl-todo-highlight-punctuation ":"
hl-todo-keyword-faces
'(;; For reminders to change or add something at a later date.
("TODO" warning bold)
;; For code (or code paths) that are broken, unimplemented, or slow,
;; and may become bigger problems later.
("FIXME" error bold)
;; For code that needs to be revisited later, either to upstream it,
;; improve it, or address non-critical issues.
("REVIEW" font-lock-keyword-face bold)
;; For code smells where questionable practices are used
;; intentionally, and/or is likely to break in a future update.
("HACK" font-lock-constant-face bold)
;; For sections of code that just gotta go, and will be gone soon.
;; Specifically, this means the code is deprecated, not necessarily
;; the feature it enables.
("DEPRECATED" font-lock-doc-face bold)
;; Extra keywords commonly found in the wild, whose meaning may vary
;; from project to project.
("NOTE" success bold)
("BUG" error bold)
("XXX" font-lock-constant-face bold)))
)Show indendation
(use-package indent-guide
:hook
(prog-mode . indent-guide-mode)
:config
(setq indent-guide-char "│")) ;; Set the character used for the indent guide.Which-key is a helper utility for keychords (which key to press).
(use-package which-key
:ensure nil ;; Don't install which-key because it's now built-in
:hook (after-init . which-key-mode)
:diminish
:custom
(which-key-side-window-location 'bottom)
(which-key-sort-order #'which-key-key-order-alpha) ;; Same as default, except single characters are sorted alphabetically
(which-key-sort-uppercase-first nil)
(which-key-add-column-padding 1) ;; Number of spaces to add to the left of each column
(which-key-min-display-lines 6) ;; Increase the minimum lines to display because the default is only 1
(which-key-idle-delay 0.8) ;; Set the time delay (in seconds) for the which-key popup to appear
(which-key-max-description-length 25)
(which-key-allow-imprecise-window-fit nil)) ;; Fixes which-key window slipping out in Emacs DaemonRemoves whitespace from the ends of lines.
(use-package ws-butler
:hook (after-init . ws-butler-global-mode))Emacs Start Up Profiler
(use-package esup
:defer
:custom
(esup-depth 0))