;;; init.el --- GNU Emacs Initialization File -*- lexical-binding: t; -*- ;; Author: Andrew Scott ;; Keywords: convenience, tools ;; URL: https://codeberg.org/andyscott/dotfiles ;; This file is not part of GNU Emacs. ;; Copyright (c) 2023 Andrew Scott ;; MIT No Attribution ;; Permission is hereby granted, free of charge, to any person obtaining a copy of this ;; software and associated documentation files (the "Software"), to deal in the Software ;; without restriction, including without limitation the rights to use, copy, modify, ;; merge, publish, distribute, sublicense, and/or sell copies of the Software, and to ;; permit persons to whom the Software is furnished to do so. ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, ;; INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A ;; PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ;;; Commentary: ;; My Emacs initialization file. ;;; Code: ;; Profile init time ;; Replace `emacs-startup-hook' w/ `elpaca-after-init-hook' to profile `Elpaca' (add-hook 'emacs-startup-hook (lambda () (message "Emacs loaded in %s with %d garbage collections." (format "%.2f seconds" (float-time (time-subtract (current-time) before-init-time))) gcs-done))) ;; View profiler report after init ;; (profiler-start 'cpu+mem) ;; (add-hook 'elpaca-after-init-hook (lambda () (profiler-stop) (profiler-report))) ;; Profile function performance ;; (require 'elp) ;; (with-eval-after-load file ;; (elp-instrument-package file)) ;; (add-hook 'elpaca-after-init-hook ;; (lambda () (elp-results) (elp-restore-package (intern file)))) ;; Elpaca (defvar elpaca-installer-version 0.7) (defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory)) (defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory)) (defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory)) (defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git" :ref nil :depth 1 :files (:defaults "elpaca-test.el" (:exclude "extensions")) :build (:not elpaca--activate-package))) (let* ((repo (expand-file-name "elpaca/" elpaca-repos-directory)) (build (expand-file-name "elpaca/" elpaca-builds-directory)) (order (cdr elpaca-order)) (default-directory repo)) (add-to-list 'load-path (if (file-exists-p build) build repo)) (unless (file-exists-p repo) (make-directory repo t) (when (< emacs-major-version 28) (require 'subr-x)) (condition-case-unless-debug err (if-let ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*")) ((zerop (apply #'call-process `("git" nil ,buffer t "clone" ,@(when-let ((depth (plist-get order :depth))) (list (format "--depth=%d" depth) "--no-single-branch")) ,(plist-get order :repo) ,repo)))) ((zerop (call-process "git" nil buffer t "checkout" (or (plist-get order :ref) "--")))) (emacs (concat invocation-directory invocation-name)) ((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch" "--eval" "(byte-recompile-directory \".\" 0 'force)"))) ((require 'elpaca)) ((elpaca-generate-autoloads "elpaca" repo))) (progn (message "%s" (buffer-string)) (kill-buffer buffer)) (error "%s" (with-current-buffer buffer (buffer-string)))) ((error) (warn "%s" err) (delete-directory repo 'recursive)))) (unless (require 'elpaca-autoloads nil t) (require 'elpaca) (elpaca-generate-autoloads "elpaca" repo) (load "./elpaca-autoloads"))) (add-hook 'after-init-hook #'elpaca-process-queues) (elpaca `(,@elpaca-order)) ;; Configure `use-package' with `Elpaca' (defmacro use-feature (name &rest args) "Like `use-package' but accounting for asynchronous installation. NAME and ARGS are in `use-package'. Credit to @progfolio: https://github.com/progfolio/.emacs.d?tab=readme-ov-file#use-package" (declare (indent defun)) `(use-package ,name :ensure nil ,@args)) (elpaca elpaca-use-package (require 'elpaca-use-package) (elpaca-use-package-mode) (setopt use-package-always-ensure t)) (if debug-on-error (setopt use-package-verbose t use-package-expand-minimally nil use-package-compute-statistics t) (setopt use-package-verbose nil use-package-expand-minimally t)) ;; TODO - remove this when done profiling startup (setopt use-package-compute-statistics t) ;; Wait for `Elpaca' to process current queue (elpaca-wait) ;;; Built-in Packages: ;; Revert a buffer if the file has changed (use-feature autorevert :config (global-auto-revert-mode t) :defer 3 :init (setopt auto-revert-interval 0.01)) ;; Customize compilation & related buffers (use-feature compile :bind (:map prog-mode-map ("C-c r" . recompile)) :commands (compile recompile) :config (setopt compilation-ask-about-save nil compilation-scroll-output 'first-error)) ;; Write external customizations to /dev/null (use-feature cus-edit :init (setopt custom-file null-device)) (use-feature custom :config (setopt custom-safe-themes t)) ;; Customize fill column indicator (use-feature display-fill-column-indicator :hook ((conf-mode markdown-mode prog-mode) . display-fill-column-indicator-mode)) ;; Customize line number display (use-feature display-line-numbers :hook ((conf-mode prog-mode) . display-line-numbers-mode)) ;; Customize LSP options (use-feature eglot :bind (:map eglot-mode-map ("C-c c a" . eglot-code-actions) ("C-c c o" . eglot-code-actions-organize-imports) ("C-c c r" . eglot-rename) ("C-c c f" . eglot-format)) :config (push '(astro-mode . ("astro-ls" "--stdio" :initializationOptions (:typescript (:tsdk "/usr/lib/node_modules/typescript/lib")))) eglot-server-programs) (push '((rust-ts-mode rust-mode) . ("rustup" "run" "stable" "rust-analyzer" :initializationOptions (:check (:command "clippy")))) eglot-server-programs) (setopt eglot-autoshutdown t eglot-ignored-server-capabilities '(;; :colorProvider ; "Decorate color references" ;; :documentFormattingProvider ; "Format buffer" ;; :documentHighlightProvider ; "Highlight symbols automatically" :documentOnTypeFormattingProvider ; "On-type formatting" ;; :documentRangeFormattingProvider ; "Format portion of buffer" ;; :hoverProvider ; "Documentation on hover" :inlayHintProvider ; "Inlay hints" )) :hook ((astro-mode c-ts-mode c++-ts-mode rust-ts-mode zig-mode) . eglot-ensure)) ;; Automatic parenthesis/brackets matching (use-feature elec-pair :hook ((conf-mode markdown-mode prog-mode) . electric-pair-mode)) ;; Options defined in C source code & other misc. global customizations (use-feature emacs :bind (:map global-map ;; Disable `suspend-frame' shortcut ("C-z" . nil) ;; Escape behaves like C-g ("" . keyboard-escape-quit) ;; Resizing buffers ("S-C-" . shrink-window-horizontally) ("S-C-" . enlarge-window-horizontally) ("S-C-" . shrink-window) ("S-C-" . enlarge-window)) :config (setopt cursor-type 'bar fill-column 80 scroll-step 1 scroll-conservatively 1000 scroll-preserve-screen-position t) :init ;; Vertico (defun crm-indicator (args) (cons (format "[CRM%s] %s" (replace-regexp-in-string "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" "" crm-separator) (car args)) (cdr args))) (advice-add #'completing-read-multiple :filter-args #'crm-indicator) (setopt enable-recursive-minibuffers t ; Recursive minibuffers minibuffer-prompt-properties ; Disable prompt in minibuffer '(read-only t cursor-intangible t face minibuffer-prompt)) (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)) ;; Customize file handling & automatic backups (use-feature files :config (let ((auto_save_directory (concat xdg_cache_home "auto-save-list/"))) (unless (file-directory-p auto_save_directory) (make-directory auto_save_directory)) (setopt backup-directory-alist `((".*" . ,auto_save_directory)) auto-save-list-file-prefix (concat auto_save_directory "saves-")) auto-save-file-name-transforms `((".*" ,auto_save_directory t))) (setopt backup-by-copying t confirm-kill-processes nil delete-old-versions t kept-new-versions 5 kept-old-versions 3 require-final-newline t version-control t)) ;; Customize syntax checking (use-feature flymake :bind (:map flymake-mode-map ("C-c f d" . flymake-show-buffer-diagnostics) ("C-c f D" . flymake-show-project-diagnostics) ("C-c f n" . flymake-goto-next-error) ("C-c f p" . flymake-goto-prev-error))) ;; Customize spell checking (use-feature flyspell :hook (((git-commit-mode org-mode text-mode) . flyspell-mode) (prog-mode . flyspell-prog-mode))) ;; Customize frame behavior/cursor blinking (use-feature frame :config (setopt blink-cursor-delay 1.0 blink-cursor-interval 0.75)) ;; Ensure UTF-8 terminal encoding (use-feature mule :config (unless (display-graphic-p) (set-terminal-coding-system 'utf-8))) ;; Customize mouse wheel (use-feature mwheel :config (setopt mouse-wheel-follow-mouse t mouse-wheel-progressive-speed nil mouse-wheel-scroll-amount '(2 ((shift) . 1)))) ;; Visualize matching parenthesis/brackets (use-feature paren :hook ((conf-mode markdown-mode prog-mode) . show-paren-mode)) ;; Enable smooth mouse wheel scrolling when available (when (fboundp 'pixel-scroll-precision-mode) (use-feature pixel-scroll :config (pixel-scroll-precision-mode))) (use-feature project :config (setopt project-vc-extra-root-markers '("Cargo.toml"))) ;; Customize handling of recent files (use-feature recentf :config (setopt recentf-max-menu-items 100 recentf-max-saved-items 1000 recentf-save-file (expand-file-name "recentf" xdg_cache_home)) (recentf-mode)) ;; Customize saving mini-buffer history (use-feature savehist :config (setopt savehist-autosave-interval 120 savehist-file (expand-file-name "history" xdg_cache_home)) (savehist-mode)) ;; Customize saving place in files (use-feature saveplace :config (setopt save-place-file (expand-file-name "places" xdg_cache_home)) (save-place-mode)) ;; Unload `seq' before `Elpaca' starts building ;; https://github.com/progfolio/elpaca/issues/216#issuecomment-1868444883 (defun +elpaca-unload-seq (e) (and (featurep 'seq) (unload-feature 'seq t)) (elpaca--continue-build e)) (defun +elpaca-seq-build-steps () (append (butlast (if (file-exists-p (expand-file-name "seq" elpaca-builds-directory)) elpaca--pre-built-steps elpaca-build-steps)) (list '+elpaca-unload-seq 'elpaca--activate-package))) (use-package seq :ensure `(seq :build ,(+elpaca-seq-build-steps))) ;; "A grab-bag of basic Emacs commands" (use-feature simple :config (setopt indent-tabs-mode nil read-extended-command-predicate #'command-completion-default-include-p) :hook (((conf-mode prog-mode) . column-number-mode) (text-mode . auto-fill-mode))) ;; Customize text buffers (use-feature text-mode :config (setq-local fill-column 120)) ;; Customize tree-sitter parsing (use-feature treesit :config (push '(c++-mode . c++-ts-mode) major-mode-remap-alist) (setopt treesit-font-lock-level 4)) ;; Customize whitespace visualization & cleanup (use-feature whitespace :config (add-hook 'before-save-hook #'whitespace-cleanup) (setopt whitespace-line-column nil whitespace-style '(lines-char missing-newline-at-eof space-after-tab space-before-tab tabs trailing)) :hook ((conf-mode prog-mode text-mode) . whitespace-mode)) ;;; Packages: ;; Shows current/total matches in mode line (use-package anzu :config (global-anzu-mode) :defer 3) ;; Auto-format (use-package apheleia :defer t) ;; Extensions for `completion-at-point' (use-package cape :bind ("M-p" . cape-prefix-map)) ;; Catppuccin theme (use-package catppuccin-theme :disabled :config (setopt catppuccin-flavor 'macchiato) ;; (catppuccin-reload) ;; (load-theme 'catppuccin t) ) ;; C/C++ formatting ;; Ad hoc format file: clang-format -style=webkit -dump-config > .clang-format (use-package clang-format :commands (clang-format clang-format-buffer clang-format-region) :config (setopt clang-format-fallback-style "webkit" clang-format-style "file")) ;; Search and navigation (use-package consult :bind (;; C-c bindings in `mode-specific-map' ("C-c M-x" . consult-mode-command) ("C-c h" . consult-history) ("C-c k" . consult-kmacro) ("C-c m" . consult-man) ("C-c i" . consult-info) ([remap Info-search] . consult-info) ;; C-x bindings in `ctl-x-map' ("C-x M-:" . consult-complex-command) ; orig. repeat-complex-command ("C-x b" . consult-buffer) ; orig. switch-to-buffer ("C-x 4 b" . consult-buffer-other-window) ; orig. switch-to-buffer-other-window ("C-x 5 b" . consult-buffer-other-frame) ; orig. switch-to-buffer-other-frame ("C-x r b" . consult-bookmark) ; orig. bookmark-jump ("C-x p b" . consult-project-buffer) ; orig. project-switch-to-buffer ("C-x M-r" . consult-recent-file) ;; Custom M-# bindings for fast register access ("M-#" . consult-register-load) ("M-'" . consult-register-store) ; orig. abbrev-prefix-mark (unrelated) ("C-M-#" . consult-register) ;; Other custom bindings ("M-y" . consult-yank-pop) ; orig. yank-pop ;; M-g bindings in `goto-map' ("M-g e" . consult-compile-error) ("M-g f" . consult-flymake) ; Alternative: consult-flycheck ("M-g g" . consult-goto-line) ; orig. goto-line ("M-g M-g" . consult-goto-line) ; orig. goto-line ("M-g o" . consult-outline) ; Alternative: consult-org-heading ("M-g m" . consult-mark) ("M-g k" . consult-global-mark) ("M-g i" . consult-imenu) ("M-g I" . consult-imenu-multi) ;; M-s bindings in `search-map' ("M-s d" . consult-find) ("M-s D" . consult-locate) ("M-s g" . consult-grep) ("M-s G" . consult-git-grep) ("M-s r" . consult-ripgrep) ("M-s l" . consult-line) ("M-s L" . consult-line-multi) ("M-s k" . consult-keep-lines) ("M-s u" . consult-focus-lines) ;; Isearch integration ("M-s e" . consult-isearch-history) :map isearch-mode-map ("M-e" . consult-isearch-history) ; orig. isearch-edit-string ("M-s e" . consult-isearch-history) ; orig. isearch-edit-string ("M-s l" . consult-line) ; needed by consult-line to detect isearch ("M-s L" . consult-line-multi) ; needed by consult-line to detect isearch ;; Minibuffer history :map minibuffer-local-map ("M-s" . consult-history) ; orig. next-matching-history-element ("M-r" . consult-history) :map as/org-prefix-map ; orig. previous-matching-history-element ("h" . consult-org-heading) ("a" . consult-org-agenda)) :config (setopt consult-narrow-key "<") :init ;; Register formatting (setopt register-preview-delay 0.6 register-preview-function #'consult-register-format) ;; Register preview window (advice-add #'register-preview :override #'consult-register-window) ;; Select xref locations with preview (setopt xref-show-xrefs-function #'consult-xref xref-show-definitions-function #'consult-xref)) (use-package consult-dir :after (consult) :bind (("C-x C-d" . consult-dir) :map vertico-map ("C-x C-d" . consult-dir) ("C-x C-j" . consult-dir-jump-file))) ;; UI for the workspace/symbols procedure calls (use-package consult-eglot :after (eglot) :bind (:map eglot-mode-map ("C-c c s" . consult-eglot-symbols))) ;; In-buffer completion (use-package company :disabled :bind (:map company-active-map ("RET" . nil) ("[return]" . nil) ("TAB" . company-complete-selection) ("" . company-complete-selection) ("C-n" . company-select-next) ("C-p" . company-select-previous)) :config (setopt company-global-modes '(not gud-mode not comint-mode) company-tooltip-align-annotations t) :hook (prog-mode . company-mode)) ;; FIXME - I crash emacs (use-package corfu ;; :disabled :bind (:map corfu-map ("M-SPC" . corfu-insert-separator) ("RET" . nil)) :config (setopt corfu-auto t corfu-cycle t) (global-corfu-mode) (corfu-popupinfo-mode) :defer 3 :ensure (corfu :files (:defaults "extensions/*"))) (use-package doom-themes :disabled :config (setopt doom-themes-enable-bold t doom-themes-enable-italic t)) (use-package nimbus-theme :config (load-theme 'nimbus)) (use-package ef-themes :disabled :config (setopt ef-themes-headings '((0 variable-pitch light 1.9) (1 variable-pitch light 1.8) (2 variable-pitch regular 1.7) (3 variable-pitch regular 1.6) (4 variable-pitch regular 1.5) (5 variable-pitch 1.4) ; absence of weight means `bold' (6 variable-pitch 1.3) (7 variable-pitch 1.2) (t variable-pitch 1.1)) ef-themes-mixed-fonts t ef-themes-variable-pitch-ui t)) ;; Use `emacs-lsp-booster' with `Eglot' (use-package eglot-booster :after eglot :config (eglot-booster-mode) :ensure (eglot-booster :host github :repo "jdtsmith/eglot-booster")) ;; Command menu for items around point (use-package embark :bind (("C-." . embark-act) ("C-;" . embark-dwim) ("C-h B" . embark-bindings)) :config ;; Hide the Embark live/completions buffer mode line (push '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" nil (window-parameters (mode-line-format . none))) display-buffer-alist) :defer 3 :init (setopt prefix-help-command #'embark-prefix-help-command)) (use-package embark-consult :hook (embark-collect-mode . consult-preview-at-point-mode)) ;; Startup screen (use-package enlight :after (grid) :config (setopt enlight-content (grid-get-row `(,(enlight-menu '(("Files" ("Find File" find-file "f") ("Recent Files" consult-recent-file "r") ("Projects" project-switch-project "p") ("Open Project Buffer" consult-project-buffer "o")))) " " ,(enlight-menu '(("Org" ("Agenda" (org-agenda nil "a") "a") ("Time blocking" org-timeblock "b") ("Super agenda" (org-agenda nil "u") "u") ("Match Tags" (org-agenda nil "m") "m")))) " " ,(enlight-menu `(("Settings" ("Elpaca" elpaca-manager "L") ("Emacs" (progn (find-file ,user-init-file)) "I") ("Enlight" (progn (find-file ,user-init-file) (goto-char (point-min)) (search-forward "use-package enlight")) "E") ("Org" (progn (find-file ,(replace-regexp-in-string "init.el" "lisp/init-org.el" user-init-file))) "O"))))))) (enlight-open)) ;; Correction functions for `flyspell' (use-package flyspell-correct :after (flyspell) :bind (:map flyspell-mode-map ("C-M-." . flyspell-correct-wrapper))) ;; Grid for `enlight' (use-package grid :ensure (:host github :repo "ichernyshovvv/grid.el")) ;; Highlight keywords (use-package hl-todo :bind (:map hl-todo-mode-map ("C-c t p" . hl-todo-previous) ("C-c t n" . hl-todo-next) ("C-c t o" . hl-todo-occur) ("C-c t i" . hl-todo-insert)) :config (setopt hl-todo-highlight-punctuation ":!?" hl-todo-keyword-faces '(("DEBUG" warning bold) ("HACK" warning bold) ("FIXME" error bold) ("NOTE" highlight italic) ("REVIEW" highlight italic) ("TODO" highlight bold))) :ensure (hl-todo :depth nil) :hook (prog-mode . hl-todo-mode)) ;; Icons for `corfu' (use-package kind-icon :disabled :after (corfu) :config (push #'kind-icon-margin-formatter corfu-margin-formatters) (setopt kind-icon-default-face 'corfu-default)) ;; Git (use-package transient ; Must declare before magit :defer t) (use-package magit :bind ("C-M-;" . magit-status) :config (setopt magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1 transient-history-file (expand-file-name "transient-history" xdg_cache_home))) (use-package magit-todos :hook (magit-mode . magit-todos-mode)) ;; Better annotations (use-package marginalia :config (marginalia-mode) :defer 1) ;;; File format/markup support (use-package markdown-mode :commands (markdown-mode) :config (setq-local fill-column 120)) ;; Better C++ font locking (use-package modern-cpp-font-lock :hook (c++-ts-mode . modern-c++-font-lock-mode)) ;; Mode line (use-package moody :config (setq x-underline-at-descent-line t) (moody-replace-eldoc-minibuffer-message-function) (moody-replace-mode-line-buffer-identification) (moody-replace-mode-line-front-space) (moody-replace-vc-mode) :defer 1) (use-package minions :after (moody) :config (minions-mode)) ;; Various nerd icon packages (use-package nerd-icons :defer 1) (use-package nerd-icons-completion :after (nerd-icons marginalia) :config (nerd-icons-completion-mode) :hook (marginalia-mode . nerd-icons-completion-marginalia-setup)) (use-package nerd-icons-corfu :after (nerd-icons corfu) :config (push #'nerd-icons-corfu-formatter corfu-margin-formatters)) (use-package nerd-icons-dired :hook (dired-mode . nerd-icons-dired-mode)) (use-package nerd-icons-ibuffer :hook (ibuffer-mode . nerd-icons-ibuffer-mode)) ;; Completion style (use-package orderless :config (setopt completion-styles '(orderless basic) completion-category-overrides '((file (styles basic partial-completion))) orderless-matching-styles '(orderless-regexp orderless-literal orderless-initialism)) :defer 1) ;; Project Management (use-package projectile :disabled :bind ("C-c p" . projectile-command-map) :config (setopt projectile-known-projects-file (expand-file-name "projectile-bookmarks" xdg_cache_home) projectile-project-search-path '(("~/Nextcloud/Projects/src/" . 2))) (push "*node_modules" projectile-globally-ignored-directories) (projectile-mode)) ;; Visualize color names (use-package rainbow-mode :hook ((conf-mode prog-mode toml-ts-mode) . rainbow-mode)) ;; `gud' rewrite with additional features (use-package realgud :defer t) ;; `realgud' front-end for LLDB (use-package realgud-lldb :defer t) (use-package rust-mode :init (setopt rust-mode-treesitter-derive t) :commands (rust-mode)) ;; Automatically download tree-sitter grammars (use-package treesit-auto :defer 1 :config (setopt treesit-auto-install t) (setq as/c-tsauto-config (make-treesit-auto-recipe :lang 'c :ts-mode 'c-ts-mode :remap 'c-mode :url "https://github.com/tree-sitter/tree-sitter-c" :revision "v0.20.7" :ext "\\.c\\'")) (setq as/cpp-tsauto-config (make-treesit-auto-recipe :lang 'cpp :ts-mode 'c++-ts-mode :remap 'c++-mode :url "https://github.com/tree-sitter/tree-sitter-cpp" :revision "v0.21.0" :ext "\\.cpp\\'")) (push as/c-tsauto-config treesit-auto-recipe-list) (push as/cpp-tsauto-config treesit-auto-recipe-list) ;;(add-to-list 'treesit-auto-recipe-list as/cpp-tsauto-config) (treesit-auto-add-to-auto-mode-alist 'all) (global-treesit-auto-mode)) ;; Better undo/redo (use-package undo-fu :bind (("C-z" . undo-fu-only-undo) ("C-M-z" . undo-fu-only-redo)) :defer 1) (use-package undo-fu-session :after (undo-fu) :config (setopt undo-fu-session-incompatible-files '("/COMMIT_EDITMSG\\'" "/git-rebase-todo\\'") undo-fu-session-directory (concat xdg_cache_home "undo-fu-session/")) (undo-fu-session-global-mode)) ;; Mini-buffer completion UI (use-package vertico :config (setopt vertico-cycle t vertico-count 10 vertico-resize t vertico-scroll-margin 1 completion-ignore-case t read-buffer-completion-ignore-case t read-file-name-completion-ignore-case t) :init (vertico-mode)) ;; Web and SSG (define-derived-mode astro-mode web-mode "astro") (use-package web-mode :config (setopt web-mode-attribute-indent-offset 2 web-mode-code-indent-offset 2 web-mode-css-indent-offset 2 web-mode-markup-indent-offset 2 web-mode-enable-front-matter-block t web-mode-engines-alist '(("blade" . "\\.blade\\.") ("razor" . "\\.cshtml\\'"))) :mode ("\\.astro\\'" . astro-mode) ("\\.\\(cshtml\\|html?\\|razor\\)\\'" . web-mode)) ;; Show keybind hints (use-package which-key :config (setopt which-key-idle-delay 0.3 ;; which-key-sort-order 'which-key-description-order which-key-side-window-max-width 0.33) (which-key-mode) :defer 1) ;; Expand abbreviations to templates (use-package yasnippet :bind (:map yas-minor-mode-map ("C-c y i" . yas-insert-snippet) ("C-c y v" . yas-visit-snippet-file)) :config (yas-reload-all) :hook (prog-mode . yas-minor-mode)) (use-package yasnippet-snippets :after (yasnippet)) (use-package consult-yasnippet :after (yasnippet) :bind (:map yas-minor-mode-map ("C-c y c" . consult-yasnippet))) ;; YAML (use-package yaml-pro :hook (yaml-ts-mode . yaml-pro-ts-mode)) ;; Zig (use-package reformatter ; required for `zig-format' functions :after (zig-mode)) (use-package zig-mode :commands (zig-mode) :config (defun zig-compile () (interactive) (save-buffer) (zig--run-cmd "build")) (setq-local fill-column 100) (setopt zig-format-on-save nil)) (push "~/.config/emacs/lisp/" load-path) (require 'init-org) ;;; init.el ends here