Skip to content

trevorbernard/emacs.d

Repository files navigation

Emacs Configuration

Configuration

This is my emacs, there are many like it, but this one is mine…

Table of Contents

Getting Started

I currently use 30.1 on both Linux and Mac systems. YMMV on Windows or different versions of Emacs.

You will need the following already installed for this configuration to run correctly.

I strongly suggest you remap your Caps Lock key to Control to help reduce the onset of Emacs pinky. I even go further and have a new key binding for M-x, so you are hitting Ctrl instead of Alt.

Early Initialization

Early initialization happens before the main init file loads. This is where we configure the package system, set up garbage collection optimization, and handle frame appearance for better startup performance.

;;; -*- lexical-binding: t -*-

(setq process-adaptive-read-buffering nil)

(add-hook 'emacs-startup-hook
          (lambda () (message "Emacs ready in %s with %d garbage collections."
                              (format "%.2f seconds" (float-time (time-subtract after-init-time before-init-time)))
                              gcs-done)))

(setq gc-cons-threshold most-positive-fixnum
      gc-cons-percentage 0.9)

(set-display-table-slot standard-display-table 'vertical-border ?|)

;; Set frame parameters before frame creation
(setq default-frame-alist
      (append default-frame-alist
              '((background-color . "#2b303b")
                (foreground-color . "#c0c5ce")
                (fullscreen . maximized)
                (menu-bar-lines . 0)
                (tool-bar-lines . 0)
                (vertical-scroll-bars)
                (horizontal-scroll-bars)
                (internal-border-width . 0))))

(set-face-attribute 'mode-line nil :background 'unspecified)


(menu-bar-mode -1)
(when (fboundp 'tool-bar-mode)
  (tool-bar-mode -1))
(when (fboundp 'scroll-bar-mode)
  (scroll-bar-mode -1))

;; suppresses the message
(defun display-startup-echo-area-message ())

(setq inhibit-startup-message t
      inhibit-startup-echo-area-message "tbernard")

(setq frame-inhibit-implied-resize t
      frame-resize-pixelwise t)

;; enable smooth scrolling
(pixel-scroll-precision-mode t)

;; Native compilation configuration - consolidated here to avoid race conditions
(when (and (fboundp 'native-comp-available-p)
           (native-comp-available-p))
  (let ((eln-cache-dir (expand-file-name "eln-cache/" user-emacs-directory)))
    (condition-case err
        (progn
          ;; Ensure eln-cache directory exists and is writable
          (unless (file-directory-p eln-cache-dir)
            (make-directory eln-cache-dir t))

          ;; Only add to path if directory is actually writable
          (when (and (boundp 'native-comp-eln-load-path)
                     (file-writable-p eln-cache-dir))
            (add-to-list 'native-comp-eln-load-path eln-cache-dir))

          ;; Configure native compilation settings
          (setq native-comp-speed 2
                comp-deferred-compilation t
                native-comp-jit-compilation t
                ;; Dynamic async jobs based on CPU cores (max 4, min 1)
                native-comp-async-jobs-number (min 4 (max 1 (/ (num-processors) 2)))
                ;; Enable warnings only for debugging - set to t if compilation fails
                native-comp-async-report-warnings-errors nil)

          (message "Native compilation configured: %d async jobs, cache: %s"
                   native-comp-async-jobs-number eln-cache-dir))

      (error
       (message "Native compilation setup failed: %s - falling back to defaults" err)
       ;; Minimal fallback configuration
       (setq native-comp-speed 1
             comp-deferred-compilation nil
             native-comp-async-report-warnings-errors t)))))

(setenv "LSP_USE_PLISTS" "true")

;; Bootstrap package system and use-package for better startup performance
(require 'package)

(setq package-archives '(("melpa" . "https://melpa.org/packages/")
                         ("melpa-stable" . "https://stable.melpa.org/packages/")
                         ("gnu" . "https://elpa.gnu.org/packages/")))

;; pin projectile to melpa-stable
(setq package-pinned-packages
      '((projectile . "melpa-stable")))

(unless package--initialized
  (package-initialize))

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(eval-when-compile
  (setq use-package-always-defer t
        use-package-verbose nil  ; Set to t for debugging, nil for performance
        use-package-minimum-reported-time 0.1)
  (require 'use-package))

(provide 'early-init)

Preamble

;;; -*- lexical-binding: t -*-
(setq read-process-output-max (* 10 1024 1024))
(setq process-adaptive-read-buffering nil)

(setq treemacs-no-load-time-warnings t)

(unless (boundp 'image-scaling-factor)
  (setq image-scaling-factor 1.0))

General use-package settings

Package system and use-package are now bootstrapped in early-init.el for better startup performance. This ensures use-package is available before the main configuration loads.

Emacs Initialization

I like to have my Emacs clean, crisp, and minimal. Disable the menu bar, tool bar, and scroll bar. Protip: Learn the Emacs navigation key strokes until they are second nature. You can thank me later.

Package Settings

Package system is now handled entirely in early-init.el for optimal startup performance. The package bootstrap, load-path setup, and use-package configuration are all done before the main configuration loads.

;; Only set load-prefer-newer since package system is handled in early-init.el
(setq load-prefer-newer t)

UI & Appearance

Visual configuration for a clean, modern Emacs experience with consistent theming and helpful visual indicators.

Theme Configuration

(use-package timu-spacegrey-theme
  :ensure t
  :custom
  (timu-spacegrey-transparent-background t)
  :hook
  (after-init . (lambda () (load-theme 'timu-spacegrey t))))

(with-eval-after-load 'timu-spacegrey-theme
  (set-face-attribute 'default nil :background "unspecified"))

Mode Line

(use-package doom-modeline
  :ensure t
  :hook (after-init . doom-modeline-mode))

Visual Indicators

(use-package rainbow-delimiters
  :ensure t
  :defer t
  :hook ((prog-mode . rainbow-delimiters-mode)))

Platform-Specific Configuration

Different operating systems and display environments require specific configurations for optimal Emacs integration.

macOS Configuration

(when (eq system-type 'darwin)
 (use-package exec-path-from-shell
   :ensure t
   :config
   (exec-path-from-shell-initialize))

 ;; Mac file handling - move files to dedicated Emacs trash
 (setq delete-by-moving-to-trash t)
 (setq trash-directory "~/.Trash/emacs")

 ;; Display preferences for macOS
 (setq ns-use-native-fullscreen t)
 (setq ns-use-thin-smoothing t)
 (setq ns-pop-up-frames nil)

 ;; Avoid dired issues specific to macOS
 (setq dired-use-ls-dired nil))

Personal

That’s me.

(setq user-full-name "Trevor Bernard"
      user-mail-address "[email protected]")

Terminal & Clipboard Integration

Modern Emacs needs seamless integration between terminal and GUI environments, especially when working over SSH or in mixed Wayland/X11 setups. This section consolidates all terminal-specific configurations and clipboard handling.

Wayland Clipboard Integration

;; Configure Wayland clipboard integration immediately if needed
(when (getenv "WAYLAND_DISPLAY")
  ;; Without this, copy and pasting from other wayland apps into
  ;; emacs-pgtk doesn't work.
  ;; https://www.emacswiki.org/emacs/CopyAndPaste#h5o-4
  (setq wl-copy-process nil)
  (defun wl-copy (text)
    (setq wl-copy-process (make-process :name "wl-copy"
                                        :buffer nil
                                        :command '("wl-copy" "-f" "-n")
                                        :connection-type 'pipe
                                        :noquery t))
    (process-send-string wl-copy-process text)
    (process-send-eof wl-copy-process))
  (defun wl-paste ()
    (if (and wl-copy-process (process-live-p wl-copy-process))
        nil ; should return nil if we're the current paste owner
      (shell-command-to-string "wl-paste -n | tr -d \r")))
  (setq interprogram-cut-function 'wl-copy)
  (setq interprogram-paste-function 'wl-paste))

Terminal Mouse & Display Support

;; Enable mouse support in terminal immediately
(unless (display-graphic-p)
  (xterm-mouse-mode t)
  (set-face-inverse-video 'vertical-border nil)
  (set-face-background 'vertical-border (face-background 'default))
  (set-display-table-slot standard-display-table 'vertical-border (make-glyph-code ?│))
  ;; Define x-hide-tip as no-op for terminal mode
  (unless (fboundp 'x-hide-tip)
    (defun x-hide-tip ())))

Terminal Emulator

vterm provides a fully-fledged terminal emulator that handles escape sequences properly, making it superior to the built-in term/ansi-term.

(use-package vterm
  :defer t
  :ensure t
  :custom
  (vterm-always-compile-module t))

OSC-52 Clipboard Support

When working in a terminal over SSH, OSC-52 allows yanked text in Emacs to become available on the host machine’s clipboard.

(use-package clipetty
  :ensure t
  :bind ("M-w" . clipetty-kill-ring-save))

Key Bindings

Global key bindings and keyboard shortcuts for improved ergonomics.

Basic Key Bindings

;; Disable minimize keys in GUI immediately
(when window-system
  (keymap-global-set "C-z" 'ignore)
  (keymap-global-set "C-x C-z" 'ignore))

Invoke M-x without the Alt key

M-x is one of the most widely used key combinations in Emacs but it’s also the most annoying. You have to scrunch your left thumb and forefinger in the most uncomfortable RSI-inducing way.

I choose to rebind M-x to C-x C-m because of an article Steve Yegge wrote called: Effective Emacs. This allows you to keep your fingers on the home row if you have Caps Lock mapped to Control. With some practice, it will become second-nature.

;; Set up M-x alternatives immediately
(keymap-global-set "C-x C-m" 'execute-extended-command)
(keymap-global-set "C-c C-m" 'execute-extended-command)

Development Bindings

;; Cider REPL jack-in - long-time habit
(keymap-global-set "C-c C-j" 'cider-jack-in)

;; Magit bindings for git operations
(keymap-global-set "C-x g" 'magit-status)
(keymap-global-set "C-c g" 'magit-file-dispatch)

Evil Mode

VIM motions are clearly the superior way to edit text but I’m hardcoded to Emacs text editting. This will be a long transition.

(use-package evil :ensure t)

Editor Behavior & Preferences

Core Emacs settings that affect how the editor behaves and feels during everyday use.

Basic Editor Behavior

(setq
 ;; Allow short answers 'y' or 'n'
 use-short-answers t
 ;; Make pgup/dn remember current line
 scroll-preserve-screen-position t
 ;; Disable the annoying bell
 ring-bell-function 'ignore)

;; Auto revert buffers when files change on disk
(global-auto-revert-mode t)
;; Show column number in mode line
(column-number-mode 1)
;; Allow delete of selection when typing
(delete-selection-mode 1)
;; Syntax highlighting everywhere
(global-font-lock-mode 1)
;; Highlight matching parentheses
(show-paren-mode 1)
;; Highlight selected regions
(transient-mark-mode 1)

File Handling & Backup Preferences

By default, Emacs generates backup files, auto-save files, and lockfiles. With modern system stability and version control, these are often redundant.

(setq
 make-backup-files nil    ; No backup~ files
 auto-save-default nil    ; No #autosave# files
 create-lockfiles nil)    ; No .#lock files

Indentation & Formatting

;; Use spaces instead of tabs
(setq-default indent-tabs-mode nil)
(setq-default c-basic-offset 4)
(setq-default tab-width 8)

;; Text width and line handling
(setq-default fill-column 80)
(setq-default truncate-lines nil)

Enable Useful Functions

;; Allow these functions without confirmation warnings
(put 'downcase-region 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'upcase-region 'disabled nil)

Development

When in programming mode, I bind C-c C-c to run 'compile. This is a huge time-saver when working on projects - just hit the key combo and watch your code build.

(use-package prog-mode
  :custom
  (show-trailing-whitespace t)
  (display-line-numbers-type 'relative)
  :hook (prog-mode . display-line-numbers-mode))

Experiment with indent-bars

(use-package indent-bars
  :load-path "~/code/indent-bars"
  :hook ((prog-mode . indent-bars-mode)))

Projectile Mode

Bind projectile to C-c p and enable by default.

(use-package projectile
  :ensure t
  :diminish projectile-mode
  :custom
  (projectile-project-search-path '("~/p/" "~/code/" "~/.emacs.d/"))
  (projectile-completion-system 'ivy)
  (projectile-enable-caching t)
  (projectile-indexing-method 'alien)
  (projectile-sort-order 'recently-active)
  :bind-keymap ("C-c p" . projectile-command-map)
  :bind (:map projectile-command-map
              ("C" . projectile-invalidate-cache))
  :commands (projectile-find-file projectile-switch-project projectile-command-map)
  :hook (after-init . projectile-mode))

Company

(use-package company
  :ensure t
  :bind
  (:map company-active-map
        ("C-n". company-select-next)
        ("C-p". company-select-previous)
        ("M-<". company-select-first)
        ("M->". company-select-last))
  :hook (prog-mode . #'company))

Magit

C-c is reserved for the user. Add a more friendly binding for magit-file-dispatch

(use-package magit
  :ensure t
  :commands (magit-status magit-file-dispatch))

Paredit

Some handy dandy paredit shortcuts

On Mac, ^-left and ^-right are bound to Mission Control. Go to `System Preferences > Keyboard > Shortcuts > Mission Control` and change the settings for “Move left a space” and “Move right a space” or disable them completely.

(use-package paredit
  :ensure t
  :bind
  (:map paredit-mode-map
        ("C-<right>" . paredit-forward-slurp-sexp)
        ("C-<left>" . paredit-forward-barf-sexp)
        ("C-<backspace>" . paredit-backward-kill-word)
        ("RET" . nil))
  :hook ((cider-repl-mode
          clojure-mode
          emacs-lisp-mode
          eval-expression-minibuffer-setup
          ielm-mode
          inf-clojure-mode-hook
          lisp-interaction-mode
          lisp-mode
          scheme-mode) . paredit-mode))

Language Configurations

Programming language-specific configurations and integrations.

Clojure

I don’t like my cider to be bleeding edge since it’s caused compatibility problems in the past so pin it to melpa-stable.

(use-package clojure-mode
  :ensure t
  :defer t
  :config
  (setq clojure-align-forms-automatically t)
  (eldoc-add-command 'paredit-backward-delete 'paredit-close-round)
  (add-hook 'clojure-mode-hook #'subword-mode))

(use-package inf-clojure
  :ensure t
  :defer t
  :config
  (add-hook 'inf-clojure-mode-hook #'rainbow-delimiters-mode))

(use-package cider
  :ensure t
  :defer t
  :commands cider-jack-in
  :custom
  (nrepl-log-messages t)
  (cider-repl-use-clojure-font-lock t)
  (cider-repl-display-help-banner nil))

I have long since used this key binding to jack into a repl. My fingers are programmed this way.

Elisp

;; eldoc-mode is enabled by default in emacs-lisp-mode since Emacs 25
;; No need to explicitly add hook

Org Mode

I almost exclusively use C-j in place of hitting the enter key. The problem is that it’s bound to the org-return-indent function. This is very annoying when you are in org-mode. So instead of trying to remap my brain, I’ll remap it to newline.

(use-package ob-rust
  :ensure t)

(use-package org
  :ensure t
  :bind
  (:map
   org-mode-map
   ("C-j" . org-return)
   ("C-c ]" . org-ref-insert-link)
   ("C-c l" . org-store-link)
   ("C-c a" . org-agenda)
   ("C-c c" . org-capture))
  :config
  (turn-on-auto-fill)
  (org-babel-do-load-languages
   'org-babel-load-languages '((rust . t)
                               (shell . t))))

Exporting to PDF

In order to export to PDF, I choose to use basictex and install packages only when they are missing.

brew reinstall --cask basictex
sudo tlmgr update --self
sudo tlmgr install wrapfig
sudo tlmgr install capt-of

JavaScript

(use-package js
  :ensure t
  :defer t
  :config
  (setq js-indent-level 2))

CSS

(use-package css-mode
  :ensure t
  :defer t
  :config
  (setq css-indent-level 2))

Flycheck

(use-package flycheck
  :ensure t
  :config
  (flycheck-define-checker python-ruff
    "A Python syntax and style checker using the ruff utility.
To override the path to the ruff executable, set
`flycheck-python-ruff-executable'.
See URL `http://pypi.python.org/pypi/ruff'."
    :command ("ruff"
              "check"
              "--output-format=text"
              (eval (when buffer-file-name
                      (concat "--stdin-filename=" buffer-file-name)))
              "-")
    :standard-input t
    :error-filter (lambda (errors)
                    (let ((errors (flycheck-sanitize-errors errors)))
                      (seq-map #'flycheck-flake8-fix-error-level errors)))
    :error-patterns
    ((warning line-start
              (file-name) ":" line ":" (optional column ":") " "
              (id (one-or-more (any alpha)) (one-or-more digit)) " "
              (message (one-or-more not-newline))
              line-end))
    :modes (python-mode python-ts-mode))

  :hook (python-mode . (lambda ()
                         (unless (bound-and-true-p org-src-mode)
                           (when (buffer-file-name)
                             (setq-local flycheck-checkers '(python-ruff))
                             (flycheck-mode)))))

  :bind (:map flycheck-mode-map
              ("M-n" . flycheck-next-error)
              ("M-p" . flycheck-previous-error))

  :hook ((prog-mode . flycheck-mode)
         (text-mode . flycheck-mode)))

Flyspell

(use-package flyspell
  :ensure t
  :defer t
  :commands (flyspell-mode flyspell-prog-mode)
  :custom
  (flyspell-issue-welcome-flag nil)
  (flyspell-issue-message-flag nil)
  (flyspell-mark-duplications-flag nil)
  (ispell-program-name "aspell")
  (ispell-list-command "list")
  :bind (:map flyspell-mouse-map
              ([down-mouse-3] . flyspell-correct-word)
              ([mouse-3] . undefined))
  :hook (((text-mode org-mode markdown-mode) . flyspell-mode)
         (prog-mode . flyspell-prog-mode)))

Markdown

(use-package ox-gfm
  :ensure t)

(use-package markdown-mode
  :ensure t
  :mode (("\\.md\\'" . gfm-mode)
         ("\\.markdown\\'" . gfm-mode)))

Git

Use diff-mode when editing a git commit message

(add-to-list 'auto-mode-alist '("COMMIT_EDITMSG$" . diff-mode))

Web Development

Tree-sitter is a game-changer for syntax highlighting and code navigation. It’s a parser generator tool that builds concrete syntax trees for source files, which enables much more accurate syntax highlighting and structural editing than regex-based modes. Emacs 29+ has built-in support for it.

(use-package treesit
  :mode (("\\.tsx\\'" . tsx-ts-mode)
         ("\\.js\\'"  . typescript-ts-mode)
         ("\\.mjs\\'" . typescript-ts-mode)
         ("\\.mts\\'" . typescript-ts-mode)
         ("\\.cjs\\'" . typescript-ts-mode)
         ("\\.ts\\'"  . typescript-ts-mode)
         ("\\.jsx\\'" . tsx-ts-mode)
         ("\\.json\\'" .  json-ts-mode)
         ("\\.yaml\\'" .  yaml-ts-mode)
         ("\\.Dockerfile\\'" . dockerfile-ts-mode))
  :preface
  (defvar os/treesit-grammars-installed nil
    "Cache variable to track if tree-sitter grammars have been checked/installed.")

  (defvar os/treesit-grammar-cache-file
    (expand-file-name "treesit-grammars-installed" user-emacs-directory)
    "File to persist tree-sitter grammar installation status.")

  (defun os/setup-install-grammars ()
    "Install Tree-sitter grammars if they are absent.
Uses caching to avoid checking on every startup - only runs once per session
or when explicitly called interactively."
    (interactive)
    (when (and (fboundp 'treesit-available-p)
               (treesit-available-p)
               (or (called-interactively-p 'any)
                   (not os/treesit-grammars-installed)
                   (not (file-exists-p os/treesit-grammar-cache-file))))
      ;; Ensure treesit-language-source-alist is bound
      (unless (boundp 'treesit-language-source-alist)
        (setq treesit-language-source-alist nil))

      (let ((grammars-to-install '())
            (grammar-sources '((css . ("https://github.com/tree-sitter/tree-sitter-css" "v0.20.0"))
                               (scss . ("https://github.com/serenadeai/tree-sitter-scss"))
                               (bash "https://github.com/tree-sitter/tree-sitter-bash")
                               (html . ("https://github.com/tree-sitter/tree-sitter-html" "v0.20.1"))
                               (javascript . ("https://github.com/tree-sitter/tree-sitter-javascript" "v0.21.2" "src"))
                               (java . ("https://github.com/tree-sitter/tree-sitter-java"))
                               (json . ("https://github.com/tree-sitter/tree-sitter-json" "v0.20.2"))
                               (python . ("https://github.com/tree-sitter/tree-sitter-python" "v0.20.4"))
                               (go "https://github.com/tree-sitter/tree-sitter-go" "v0.20.0")
                               (markdown "https://github.com/ikatyang/tree-sitter-markdown")
                               (make "https://github.com/alemuller/tree-sitter-make")
                               (elisp "https://github.com/Wilfred/tree-sitter-elisp")
                               (cmake "https://github.com/uyha/tree-sitter-cmake")
                               (c . ("https://github.com/tree-sitter/tree-sitter-c" "v0.20.7"))
                               (cpp "https://github.com/tree-sitter/tree-sitter-cpp")
                               (toml "https://github.com/tree-sitter/tree-sitter-toml")
                               (tsx . ("https://github.com/tree-sitter/tree-sitter-typescript" "v0.20.3" "tsx/src"))
                               (typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "v0.20.3" "typescript/src"))
                               (yaml . ("https://github.com/ikatyang/tree-sitter-yaml" "v0.5.0"))
                               (rust . ("https://github.com/tree-sitter/tree-sitter-rust" "v0.20.3" "src"))
                               (just "https://github.com/IndianBoy42/tree-sitter-just")
                               (ruby "https://github.com/tree-sitter/tree-sitter-ruby"))))

        ;; First pass: add all grammars to source list and collect missing ones
        (dolist (grammar grammar-sources)
          (add-to-list 'treesit-language-source-alist grammar)
          (unless (treesit-language-available-p (car grammar))
            (push grammar grammars-to-install)))

        ;; Install missing grammars if any
        (when grammars-to-install
          (message "Installing %d missing tree-sitter grammars..." (length grammars-to-install))
          (dolist (grammar grammars-to-install)
            (condition-case err
                (treesit-install-language-grammar (car grammar))
              (error (message "Failed to install grammar %s: %s" (car grammar) err)))))

        ;; Mark as completed and persist to file
        (setq os/treesit-grammars-installed t)
        (with-temp-file os/treesit-grammar-cache-file
          (insert (format "Last checked: %s\n" (current-time-string))))
        (when (called-interactively-p 'any)
          (message "Tree-sitter grammar check completed.")))))

  ;; Remap traditional modes to tree-sitter modes
  ;; This is a huge improvement for syntax highlighting
  (dolist (mapping
           '((bash-mode . bash-ts-mode)
             (c++-mode . c++-ts-mode)
             (c-mode . c-ts-mode)
             (c-or-c++-mode . c-or-c++-ts-mode)
             (css-mode . css-ts-mode)
             (java-mode . java-ts-mode)
             (js-json-mode . json-ts-mode)
             (js-mode . typescript-ts-mode)
             (js2-mode . typescript-ts-mode)
             (json-mode . json-ts-mode)
             (python-mode . python-ts-mode)
             (scss-mode . scss-ts-mode)
             (sh-base-mode . bash-ts-mode)
             (sh-mode . bash-ts-mode)
             (ruby-mode . ruby-ts-mode)
             (typescript-mode . typescript-ts-mode)))
    (add-to-list 'major-mode-remap-alist mapping))
  :config
  ;; Check grammars once after init, not on every prog-mode buffer
  (add-hook 'after-init-hook
            (lambda () (run-with-idle-timer 2.0 nil #'os/setup-install-grammars))))

Language Server Protocol (LSP)

LSP is a game-changer for IDE-like features in Emacs. It provides code completion, go-to-definition, find references, and much more. I use it for most of my programming languages.

(use-package ivy
  :ensure t
  :init
  (ivy-mode))

(use-package counsel
  :ensure t
  :after ivy
  :hook (ivy-mode . counsel-mode))

(use-package lsp-ivy
  :ensure t
  :after (lsp-mode ivy)
  :commands lsp-ivy-workspace-symbol)

(use-package lsp-ui
  :ensure t
  :after lsp-mode
  :commands lsp-ui-mode
  :hook (lsp-mode . lsp-ui-mode)
  :config
  (setq lsp-ui-doc-enable nil))

(use-package lsp-mode
  :ensure t
  :commands (lsp lsp-deferred)
  :hook ((tsx-ts-mode typescript-ts-mode js-ts-mode python-ts-mode java-ts-mode) . lsp-deferred)
  :init
  ;; Set variables early, before package is loaded
  (setq lsp-log-io nil
        read-process-output-max (* 10 1024 1024)
        lsp-use-plists t)
  :config
  ;; Booster patch
  (defun lsp-booster--advice-json-parse (old-fn &rest args)
    (or
     (when (equal (following-char) ?#)
       (let ((bytecode (read (current-buffer))))
         (when (byte-code-function-p bytecode)
           (funcall bytecode))))
     (apply old-fn args)))

  (defun lsp-booster--advice-final-command (old-fn cmd &optional test?)
    (let ((orig-result (funcall old-fn cmd test?)))
      (if (and (not test?)
               (not (file-remote-p default-directory))
               lsp-use-plists
               (not (functionp 'json-rpc-connection))
               (executable-find "emacs-lsp-booster"))
          (progn
            (when-let ((resolved (executable-find (car orig-result))))
              (setcar orig-result resolved))
            (message "Using emacs-lsp-booster for %s!" orig-result)
            (cons "emacs-lsp-booster" orig-result))
        orig-result)))

  (advice-add (if (fboundp 'json-parse-buffer) 'json-parse-buffer 'json-read)
              :around #'lsp-booster--advice-json-parse)
  (advice-add 'lsp-resolve-final-command :around #'lsp-booster--advice-final-command))

Ruby

(use-package ruby-ts-mode
  :ensure t
  :mode "\\.rb\\'"
  :mode "Rakefile\\'"
  :mode "Gemfile\\'"
  :custom
  (ruby-indent-level 2)
  (ruby-indent-tabs-mode nil))

Rust

Rust is my language du jour. It’s slowly becoming my favourite programming language. The rustic package provides excellent integration with rust-analyzer (via LSP) and cargo.

(use-package rust-mode
  :ensure t
  :init
  (setq rust-mode-treesitter-derive t))

(use-package rustic
  :ensure t
  :after (rust-mode)
  :bind (:map rustic-mode-map
              ("M-j" . lsp-ui-imenu)
              ("M-?" . lsp-find-references)
              ("C-c C-c l" . flycheck-list-errors)
              ("C-c C-c a" . lsp-execute-code-action)
              ("C-c C-c r" . lsp-rename)
              ("C-c C-c q" . lsp-workspace-restart)
              ("C-c C-c Q" . lsp-workspace-shutdown)
              ("C-c C-c s" . lsp-rust-analyzer-status))
  :custom
  (rustic-compile-command "cargo b --release")
  (rustic-default-clippy-arguments "--all-targets --all-features -- -D warnings")
  (rust-format-on-save t)
  (rustic-ansi-faces ["black" "#bf616a" "#a3be8c" "#ecbe7b" "#2257a0" "#b48ead" "#4db5bd" "white"]))

ELISP

An Interactive Emacs Lisp Mode (IELM) gives you an Emacs Lisp shell.

(use-package ielm
  :ensure t
  :bind
  (:map ielm-map
        ("C-m" . 'ielm-return)
        ("<return>" . 'ielm-return))
  :config
  (add-hook 'ielm-mode-hook #'rainbow-delimiters-mode)
  (add-hook 'ielm-mode-hook #'paredit-mode))

OCaml

(use-package tuareg
  :ensure t)

Nix

(use-package lsp-nix
  :ensure lsp-mode
  :after (lsp-mode)
  :demand t
  :custom
  (lsp-nix-nil-formatter ["nixfmt"]))

(use-package nix-mode
  :ensure t
  :hook (nix-mode . lsp-deferred))

(use-package nixfmt
  :ensure t
  :bind
  (:map
   nix-mode-map
   ("C-c C-f" . nixpkgs-fmt-buffer)))

Terraform

(use-package terraform-mode
  :ensure t
  :hook (terraform-mode . lsp-deferred))

Justfile

(use-package just-ts-mode
  :ensure t
  :defer t
  :config
  (setq-local
   just-ts-indent-offset 2
   tab-width 2))

Java

(use-package lsp-java
  :ensure t
  :after lsp-mode
  :config
  (add-hook 'java-ts-mode-hook #'lsp))

(use-package dap-java :after (lsp-java))

Hurl mode

(use-package hurl-mode
  :ensure t
  :mode "\\.hurl\\'")

Misc

(use-package csv-mode
  :ensure t)

(use-package dockerfile-mode
  :ensure t)

(use-package yaml-mode
  :ensure t)

(use-package bnf-mode
  :ensure t)

(use-package htmlize
  :ensure t)

(use-package ag
  :ensure t)

(use-package string-inflection
  :ensure t)

(use-package envrc
  :ensure t
  :bind-keymap ("C-c e" . envrc-command-map)
  :hook (after-init . envrc-global-mode))

(use-package direnv
  :ensure t)

(use-package yasnippet
  :ensure t
  :diminish yas-minor-mode
  :commands (yas-minor-mode yas-global-mode)
  :hook ((prog-mode . yas-minor-mode)
         (org-mode . yas-minor-mode)))

(use-package dotenv-mode :ensure t)

Reset the garbage collection threshold.

(setq gc-cons-threshold (* 1024 1024 2))

About

This is my emacs, there are many like it, but this one is mine...

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •