;; -*- lexical-binding: t; -*- (setq gc-cons-threshold 100000000) (setq read-process-output-max (* 1024 1024 4)) ;; BUILT INS (use-package emacs :ensure nil :custom ;; Set custom variables to configure Emacs behavior. (auto-save-default nil) ;; Disable automatic saving of buffers. (column-number-mode t) ;; Display the column number in the mode line. (create-lockfiles nil) ;; Prevent the creation of lock files when editing. (delete-by-moving-to-trash t) ;; Move deleted files to the trash instead of permanently deleting them. (delete-selection-mode 1) ;; Enable replacing selected text with typed text. (display-line-numbers-type 'relative) ;; Use relative line numbering in programming modes. (global-auto-revert-non-file-bUffers t) ;; Automatically refresh non-file buffers. (history-length 25) ;; Set the length of the command history. (indent-tabs-mode nil) ;; Disable the use of tabs for indentation (use spaces instead). (inhibit-startup-message t) ;; Disable the startup message when Emacs launches. (initial-scratch-message "") ;; Clear the initial message in the *scratch* buffer. (ispell-dictionary "en_US") ;; Set the default dictionary for spell checking. (make-backup-files nil) ;; Disable creation of backup files. (pixel-scroll-precision-mode t) ;; Enable precise pixel scrolling. (pixel-scroll-precision-use-momentum nil) ;; Disable momentum scrolling for pixel precision. (ring-bell-function 'ignore) ;; Disable the audible bell. (split-width-threshold 300) ;; Prevent automatic window splitting if the window width exceeds 300 pixels. (switch-to-buffer-obey-display-actions t) ;; Make buffer switching respect display actions. (tab-always-indent 'complete) ;; Make the TAB key complete text instead of just indenting. (tab-width 4) ;; Set the tab width to 4 spaces. (treesit-font-lock-level 4) ;; Use advanced font locking for Treesit mode. (truncate-lines t) ;; Enable line truncation to avoid wrapping long lines. (use-dialog-box nil) ;; Disable dialog boxes in favor of minibuffer prompts. (use-short-answers t) ;; Use short answers in prompts for quicker responses (y instead of yes) (warning-minimum-level :emergency) ;; Set the minimum level of warnings to display. (context-menu-mode t) (enable-recursive-minibuffers t) :hook ;; Add hooks to enable specific features in certain modes. (prog-mode . display-line-numbers-mode) ;; Enable line numbers in programming modes. :config (set-face-attribute 'default nil :family "JetBrainsMono Nerd Font" :height 100) (when (eq system-type 'darwin) ;; Check if the system is macOS. (setq mac-command-modifier 'meta) ;; Set the Command key to act as the Meta key. (set-face-attribute 'default nil :family "JetBrainsMono Nerd Font" :height 130)) ;; Save manual customizations to a separate file instead of cluttering `init.el'. (setq custom-file (locate-user-emacs-file "custom-vars.el")) ;; Specify the custom file path. (load custom-file 'noerror 'nomessage) ;; Load the custom file quietly, ignoring errors. :init ;; Initialization settings that apply before the package is loaded. (tool-bar-mode -1) ;; Disable the tool bar for a cleaner interface. (menu-bar-mode -1) ;; Disable the menu bar for a more streamlined look. (when scroll-bar-mode (scroll-bar-mode -1)) ;; Disable the scroll bar if it is active. (global-hl-line-mode 1) ;; Disable highlight of the current line (global-auto-revert-mode 1) ;; Enable global auto-revert mode to keep buffers up to date with their corresponding files. (recentf-mode 1) ;; Enable tracking of recently opened files. (savehist-mode 1) ;; Enable saving of command history. (save-place-mode 1) ;; Enable saving the place in files for easier return. (winner-mode 1) ;; Enable winner mode to easily undo window configuration changes. (xterm-mouse-mode 1) ;; Enable mouse support in terminal mode. (file-name-shadow-mode 1) ;; Enable shadowing of filenames for clarity. (modify-coding-system-alist 'file "" 'utf-8)) (use-package eldoc :ensure nil :config (setq eldoc-idle-delay 0) :init (global-eldoc-mode)) (use-package flymake :ensure nil :hook (prog-mode . flymake-mode)) (use-package which-key :ensure nil :config (which-key-mode)) ;; MINAD STACK (use-package vertico :ensure t :init (vertico-mode) :custom (vertico-count 20) (vertico-resize t) (vertico-cycle t)) (use-package orderless :ensure t :custom (completion-styles '(orderless basic)) (completion-category-overrides '((file (styles partial-completion)))) (completion-category-defaults nil) (completion-pcm-leading-wildcard t)) ;; Emacs 31: partial-completion behaves like substring (use-package marginalia :ensure t :init (marginalia-mode)) (use-package consult :ensure t :init ;; Enhance register preview with thin lines and no mode line. (advice-add #'register-preview :override #'consult-register-window) ;; Use Consult for xref locations with a preview feature. (setq xref-show-xrefs-function #'consult-xref xref-show-definitions-function #'consult-xref)) (use-package embark :ensure t) (use-package embark-consult :ensure t :hook (embark-collect-mode . consult-preview-at-point-mode)) ;; Enable preview in Embark collect mode. (use-package corfu :ensure t :init (global-corfu-mode) (corfu-popupinfo-mode) :custom (corfu-cycle t) (corfu-auto t) ;; Only completes when hitting TAB (corfu-auto-prefix 1) ;; Trigger completion after typing 1 character (corfu-quit-no-match t) ;; Quit popup if no match (corfu-scroll-margin 5) ;; Margin when scrolling completions (corfu-max-width 50) ;; Maximum width of completion popup (corfu-min-width 50) ;; Minimum width of completion popup (corfu-popupinfo-delay 0.5) ;; Delay before showing documentation popup (completion-ignore-case t) :config (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)) (use-package nerd-icons-corfu :ensure t :after (:all corfu)) (use-package treesit-auto :ensure t :after emacs :config (treesit-auto-add-to-auto-mode-alist 'all) (global-treesit-auto-mode t)) (use-package yasnippet ; Snippets :ensure t :config (yas-global-mode)) ;; LSP BOOSTER (defun lsp-booster--advice-json-parse (old-fn &rest args) "Try to parse bytecode instead of json." (or (when (equal (following-char) ?#) (let ((bytecode (read (current-buffer)))) (when (byte-code-function-p bytecode) (funcall bytecode)))) (apply old-fn args))) (advice-add (if (progn (require 'json) (fboundp 'json-parse-buffer)) 'json-parse-buffer 'json-read) :around #'lsp-booster--advice-json-parse) (defun lsp-booster--advice-final-command (old-fn cmd &optional test?) "Prepend emacs-lsp-booster command to lsp CMD." (let ((orig-result (funcall old-fn cmd test?))) (if (and (not test?) ;; for check lsp-server-present? (not (file-remote-p default-directory)) ;; see lsp-resolve-final-command, it would add extra shell wrapper lsp-use-plists (not (functionp 'json-rpc-connection)) ;; native json-rpc (executable-find "emacs-lsp-booster")) (progn (when-let ((command-from-exec-path (executable-find (car orig-result)))) ;; resolve command from exec-path (in case not found in $PATH) (setcar orig-result command-from-exec-path)) (message "Using emacs-lsp-booster for %s!" orig-result) (cons "emacs-lsp-booster" orig-result)) orig-result))) (advice-add 'lsp-resolve-final-command :around #'lsp-booster--advice-final-command) (use-package lsp-mode :ensure t :hook (;; Replace XXX-mode with concrete major mode (e.g. python-mode) (lsp-mode . lsp-enable-which-key-integration) ;; Integrate with Which Key ((js-mode ;; Enable LSP for JavaScript tsx-ts-mode ;; Enable LSP for TSX typescript-ts-mode ;; Enable LSP for TypeScript css-ts-mode ;; Enable LSP for CSS go-ts-mode ;; Enable LSP for Go js-ts-mode ;; Enable LSP for JavaScript (TS mode) nix-ts-mode rust-ts-mode haskell-mode web-mode) . lsp-deferred)) ;; Enable LSP for Web (HTML) :commands lsp :custom (lsp-keymap-prefix "C-c l") ;; Set the prefix for LSP commands. (lsp-inlay-hint-enable nil) ;; Usage of inlay hints. (lsp-completion-provider :none) ;; Disable the default completion provider. (lsp-session-file (locate-user-emacs-file ".lsp-session")) ;; Specify session file location. (lsp-log-io nil) ;; Disable IO logging for speed. (lsp-idle-delay 0) ;; Set the delay for LSP to 0 (debouncing). (lsp-keep-workspace-alive nil) ;; Disable keeping the workspace alive. ;; Core settings (lsp-enable-xref t) ;; Enable cross-references. (lsp-auto-configure t) ;; Automatically configure LSP. (lsp-enable-links nil) ;; Disable links. (lsp-eldoc-enable-hover t) ;; Enable ElDoc hover. (lsp-enable-file-watchers nil) ;; Disable file watchers. (lsp-enable-folding nil) ;; Disable folding. (lsp-enable-imenu t) ;; Enable Imenu support. (lsp-enable-indentation t) ;; Disable indentation. (lsp-enable-on-type-formatting nil) ;; Disable on-type formatting. (lsp-enable-suggest-server-download t) ;; Enable server download suggestion. (lsp-enable-symbol-highlighting t) ;; Enable symbol highlighting. (lsp-enable-text-document-color t) ;; Enable text document color. ;; Modeline settings (lsp-modeline-code-actions-enable nil) ;; Keep modeline clean. (lsp-modeline-diagnostics-enable nil) ;; Use `flymake' instead. (lsp-modeline-workspace-status-enable t) ;; Display "LSP" in the modeline when enabled. (lsp-signature-doc-lines 1) ;; Limit echo area to one line. (lsp-eldoc-render-all t) ;; Render all ElDoc messages. ;; Completion settings (lsp-completion-enable t) ;; Enable completion. (lsp-completion-enable-additional-text-edit t) ;; Enable additional text edits for completions. (lsp-enable-snippet t) (lsp-completion-show-kind t) ;; Show kind in completions. ;; Lens settings (lsp-lens-enable t) ;; Enable lens support. ;; Headerline settings (lsp-headerline-breadcrumb-enable-symbol-numbers t) ;; Enable symbol numbers in the headerline. (lsp-headerline-arrow "▶") ;; Set arrow for headerline. (lsp-headerline-breadcrumb-enable-diagnostics nil) ;; Disable diagnostics in headerline. (lsp-headerline-breadcrumb-icons-enable nil) ;; Disable icons in breadcrumb. ;; Semantic settings (lsp-semantic-tokens-enable nil) :config (add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]\\node_modules\\'")) (use-package nix-ts-mode :ensure t :mode "\\.nix\\'") (use-package haskell-mode :ensure t) (use-package lsp-haskell :ensure t) (use-package eldoc-box :ensure t) (use-package diff-hl :ensure t :hook (find-file . (lambda () (global-diff-hl-mode) ;; Enable Diff-HL mode for all files. (diff-hl-flydiff-mode) ;; Automatically refresh diffs. (diff-hl-margin-mode))) ;; Show diff indicators in the margin. :custom (diff-hl-side 'left)) (use-package magit :ensure t :config (setopt magit-format-file-function #'magit-format-file-nerd-icons)) ;; Turns on magit nerd-icons (use-package evil :ensure t :hook (after-init . evil-mode) :init (setq evil-want-integration t) ;; Integrate `evil' with other Emacs features (optional as it's true by default). (setq evil-want-keybinding nil) ;; Disable default keybinding to set custom ones. (setq evil-want-C-u-scroll t) ;; Makes C-u scroll (setq evil-want-C-u-delete t) ;; Makes C-u delete on insert mode :config (evil-set-undo-system 'undo-tree) ;; Uses the undo-tree package as the default undo system (evil-set-leader 'normal (kbd "SPC")) (evil-set-leader 'visual (kbd "SPC")) (setq evil-want-fine-undo t)) (use-package evil-collection :ensure t :custom (evil-collection-want-find-usages-bindings t) :hook (evil-mode . evil-collection-init)) (use-package evil-surround :ensure t :after evil-collection :config (global-evil-surround-mode 1)) (use-package evil-matchit :ensure t :after evil-collection :config (global-evil-matchit-mode 1)) (use-package general :ensure t :after (evil evil-collection) :init (setq general-override-states '(insert emacs hybrid normal visual motion operator replace)) :config (general-evil-setup t) (general-define-key :states 'normal "] d" '(flymake-goto-next-error :wk "Goto next error") "[ d" '(flymake-goto-prev-error :wk "Goto prev error") "] c" '(diff-hl-next-hunk :wk "Goto next hunk") "[ c" '(diff-hl-previous-hunk :wk "Goto prev hunk") "g r" '(lsp-find-references :wk "Goto references") "K" '(eldoc-box-help-at-point :wk "Describe")) (general-define-key :states 'insert "C-y" '(corfu-complete :wk "Complete")) (general-create-definer my-leader-def :states '(normal insert visual motion emacs) :keymaps 'override :prefix "SPC" :global-prefix "C-SPC") (my-leader-def "f" '(:ignore t :wk "Find") "f c" '((lambda () (interactive) (find-file "~/.config/emacs/init.el")) :wk "Edit emacs config") "f r" '(consult-recent-file :wk "Recent files") "f f" '(consult-find :wk "Find Files") "f g" '(consult-ripgrep :wk "Ripgrep search in files") "f G" '(consult-git-grep :wk "Ripgrep search in files") "f l" '(consult-line :wk "Find line") "f i" '(consult-imenu :wk "Imenu buffer locations")) (my-leader-def "c" '(:ignore t :wk "Code") "c a" '(lsp-execute-code-action :wk "Code actions")) (my-leader-def "h" '(:ignore t :wk "Help") "h v" '(describe-variable :wk "Describe variable") "h f" '(describe-function :wk "Describe function") "h k" '(describe-key :wk "Describe key")) (my-leader-def "p" '(:ignore t :wk "Project") "p b" '(consult-project-buffer :wk "Project buffers") "p p" '(project-switch-project :wk "Project switch") "p f" '(project-find-file :wk "Project find file") "p g" '(project-find-regexp :wk "Project grep file") "p k" '(project-kill-buffers :wk "Project kill buffers") "p d" '(project-dired :wk "Project dired")) (my-leader-def "x" '(:ignore t :wk "Flymake") "x x" '(consult-flymake :wk "Show diagnostics")) (my-leader-def "g" '(:ignore t :wk "Git") "g g" '(magit-status :wk "Magit status") "g l" '(magit-log-current :wk "Magit log")) (my-leader-def "r n" '(lsp-rename :wk "Rename")) (my-leader-def "u" '(undo-tree-visualize :wk "Undo-tree"))) (use-package undo-tree :ensure t :hook (after-init . global-undo-tree-mode) :init (setq undo-tree-visualizer-timestamps t undo-tree-visualizer-diff t undo-limit 800000 ;; Limit for undo entries. undo-strong-limit 12000000 ;; Strong limit for undo entries. undo-outer-limit 120000000) ;; Outer limit for undo entries. :config (setq undo-tree-history-directory-alist '(("." . "~/.config/emacs/.cache/undo")))) (use-package dotenv-mode :ensure t) (use-package doom-modeline :ensure t :custom (doom-modeline-buffer-file-name-style 'buffer-name) ;; Set the buffer file name style to just the buffer name (without path). (doom-modeline-project-detection 'project) ;; Enable project detection for displaying the project name. (doom-modeline-buffer-name t) ;; Show the buffer name in the mode line. (doom-modeline-vcs-max-length 25) ;; Limit the version control system (VCS) branch name length to 25 characters. :config (setq doom-modeline-icon t) ;; Enable icons in the mode line if nerd fonts are used. :hook (after-init . doom-modeline-mode)) (use-package nerd-icons :ensure t) (use-package nerd-icons-dired :ensure t :hook (dired-mode . nerd-icons-dired-mode)) (use-package nerd-icons-completion :ensure t :config (nerd-icons-completion-mode) ;; Activate nerd icons for completion interfaces. (add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup)) ;; Setup icons in the marginalia mode for enhanced completion display. (use-package exec-path-from-shell :ensure t :config (exec-path-from-shell-initialize)) (use-package envrc :ensure t :init (setq envrc-show-summary-in-minibuffer nil) :hook (after-init . envrc-global-mode)) (use-package modus-themes :ensure t :config (load-theme 'modus-operandi t)) (use-package org :ensure nil :custom (org-tags-column 0) (org-return-follows-link t) (org-hide-emphasis-markers t) (org-log-into-drawer t) (org-log-done 'time) (org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "WAITING(w)" "|" "DONE(d)" "CANCELLED(c)"))) (org-capture-templates `(("i" "Inbox" entry (file "inbox.org") "* TODO %i%?") ("n" "Note" plain (file denote-last-path) #'denote-org-capture :no-save t :immediate-finish nil :kill-buffer t :jump-to-captured t) ("j" "Journal" entry (file denote-journal-path-to-new-or-existing-entry) "* %U %?\n%a" :kill-buffer t :empty-lines 1) ("@" "Inbox [email]" entry (file "inbox.org") "* Process %a %?"))) (org-refile-use-outline-path 'file) (org-outline-path-complete-in-steps nil) (org-directory "~/org") (org-agenda-files '("~/org/inbox.org" "~/org/gtd.org" "~/org/calendar.org")) (org-refile-targets '(("~/org/gtd.org" :maxlevel . 3) ("~/org/someday.org" :level . 1) ("~/org/calendar.org" :level . 1))) (org-agenda-skip-scheduled-if-done t) (org-agenda-skip-deadline-if-done t) (org-agenda-include-deadlines t) (org-agenda-include-diary t) (org-agenda-block-separator nil) (org-agenda-compact-blocks t) (org-agenda-start-with-log-mode t) :config :hook (org-mode . org-indent-mode) :init (require 'org-tempo)) (use-package org-modern :ensure t :config (global-org-modern-mode)) (use-package org-caldav :ensure t :config (setq org-caldav-url "https://nextcloud.michaelthomson.dev/remote.php/dav/calendars/mthomson") (setq org-caldav-calendar-id "personal") (setq org-caldav-inbox "~/org/calendar.org") (setq org-caldav-files nil) (setq org-icalendar-timezone "America/Toronto")) (use-package denote :ensure t :hook (dired-mode . denote-dired-mode) :bind (("C-c n n" . denote) ("C-c n r" . denote-rename-file) ("C-c n l" . denote-link) ("C-c n b" . denote-backlinks) ("C-c n d" . denote-dired) ("C-c n g" . denote-grep)) :config (setq denote-directory (expand-file-name "~/org/notes/")) (denote-rename-buffer-mode 1)) (use-package consult-denote :ensure t :bind (("C-c n f" . consult-denote-find) ("C-c n g" . consult-denote-grep)) :config (consult-denote-mode 1)) (use-package denote-journal :ensure t :commands ( denote-journal-new-entry denote-journal-new-or-existing-entry denote-journal-link-or-create-entry ) :hook (calendar-mode . denote-journal-calendar-mode) :config (setq denote-journal-directory (expand-file-name "journal" denote-directory)) (setq denote-journal-keyword "journal") (setq denote-journal-title-format 'day-date-month-year)) (use-package mu4e :ensure t :config (setq mu4e-get-mail-command (concat (executable-find "mbsync") " -a")) (setq mu4e-update-interval 300) (setq mu4e-change-filenames-when-moving t) (setq mu4e-attachment-dir "~/Downloads") ;;smtp (setq send-mail-function 'sendmail-send-it) (setq sendmail-program (executable-find "msmtp")) (setq message-sendmail-envelop-from 'header) ;; contexts (setq mu4e-contexts `(,(make-mu4e-context :name "personal" :enter-func (lambda () (mu4e-message "Opening personal")) :leave-func (lambda () (mu4e-message "Closing personal")) :match-func (lambda (msg) (when msg (string-match-p "^/personal" (mu4e-message-field msg :maildir)))) :vars '((user-mail-address . "me@michaelthomson.dev" ) (user-full-name . "Michael Thomson") (mu4e-drafts-folder . "/personal/Drafts") (mu4e-refile-folder . "/personal/Archive") (mu4e-sent-folder . "/personal/Sent") (mu4e-trash-folder . "/personal/Trash")))))) (use-package pdf-tools :ensure t)