;;; $DOOMDIR/config.el -*- lexical-binding: t; -*- (setq doom-theme 'doom-one) (setq display-line-numbers-type t) (setq org-directory "~/org/") (defun load-if-exists (f) (if (file-exists-p (expand-file-name f)) (load-file (expand-file-name f)))) (load-if-exists "~/.config/doom/secrets.el") (after! epa-file (setq epa-file-encrypt-to "dingfengwong@gmail.com")) (after! auth-source (setq auth-sources '("~/.authinfo.gpg"))) (setq epa-file-cache-passphrase-for-symmetric-encryption t) (use-package! super-save :config (super-save-mode +1) (setq super-save-auto-save-when-idle t) (setq super-save-idle-duration 1)) ;; Search bindings for consult-line (map! :n "C-s" (lambda () (interactive) (consult-line (thing-at-point 'symbol))) :n "M-S" #'consult-line :n "C-S-s" #'consult-line-multi) (after! lsp-ui (setq lsp-ui-doc-include-signature t ;; Show method signatures in docs lsp-ui-sideline-show-symbol t ;; Show symbols in the sideline lsp-ui-doc-show-with-cursor t ;; Show docs when cursor is on symbol lsp-ui-doc-max-height 30 ;; Increase doc height to show more info lsp-ui-sideline-show-hover t ;; Show hover information in sideline lsp-ui-doc-enable t ;; Enable documentation lsp-signature-auto-activate t ;; Show signature help automatically lsp-signature-render-documentation t)) ;; Include docs in signature help (after! eldoc (setq eldoc-echo-area-use-multiline-p t eldoc-echo-area-prefer-doc-buffer t)) (use-package! corfu-popupinfo :after corfu :hook (corfu-mode . corfu-popupinfo-mode) :custom (corfu-popupinfo-delay '(0.25 . 0.1)) ; Faster popup display (corfu-popupinfo-hide nil) ; Don't hide automatically ) ;; Configure Corfu for richer display (after! corfu (setq corfu-auto t ; Enable auto completion corfu-auto-prefix 2 ; Complete after 2 characters corfu-preview-current t ; Preview current candidate corfu-show-documentation t ; Show documentation in popup corfu-doc-max-height 20 ; Max height for doc popup corfu-doc-delay 0.2 ; Faster doc popup corfu-quit-no-match t) ; Quit if no match ;; Show more detailed annotations (setq corfu-show-annotations t corfu-annotate-max-width 50)) ;; If using LSP, configure to show more details (after! lsp-mode (setq lsp-completion-show-detail t ; Show method signatures lsp-completion-show-kind t ; Show completion item kind lsp-completion-show-label-description t ; Show more details in label )) (after! lsp-haskell (setq lsp-haskell-plugin-fourmolu-config-path "fourmolu -o -XImportQualifiedPost -o -XOverloadedStrings -o -XTypeApplications -o -XScopedTypeVariables -o -XGADTs -o -XDataKinds -o -XTypeFamilies -o -XFlexibleContexts -o -XFlexibleInstances -o -XMultiParamTypeClasses -o -XRankNTypes -o -XExistentialQuantification") ) (defun +org--restart-mode-h () "Restart `org-mode', but only once." (remove-hook 'doom-switch-buffer-hook #'+org--restart-mode-h 'local) (delq! (current-buffer) org-agenda-new-buffers) (let ((file buffer-file-name) (old-buffer (current-buffer)) (inhibit-redisplay t) new-buffer) (kill-buffer) (setq new-buffer (find-file file)) (unless (buffer-live-p old-buffer) (make-indirect-buffer new-buffer old-buffer 'clone)))) (defun +org--restart-mode-h () "Restart `org-mode', but only once." (remove-hook 'doom-switch-buffer-hook #'+org--restart-mode-h 'local) (delq! (current-buffer) org-agenda-new-buffers) (let ((file buffer-file-name) (inhibit-redisplay t)) (kill-buffer) (find-file file))) (defun +org--restart-mode-h () "Restart `org-mode', but only once." (remove-hook 'doom-switch-buffer-hook #'+org--restart-mode-h 'local) (quiet! (org-mode-restart)) (delq! (current-buffer) org-agenda-new-buffers) (run-hooks 'find-file-hook)) (add-hook! 'org-agenda-finalize-hook (defun +org-exclude-agenda-buffers-from-workspace-h () "Don't associate temporary agenda buffers with current workspace." (when (and org-agenda-new-buffers (bound-and-true-p persp-mode) (not org-agenda-sticky)) (let (persp-autokill-buffer-on-remove) (persp-remove-buffer org-agenda-new-buffers (get-current-persp) nil))))) (use-package org :defer t :config (defalias '+org--restart-mode-h #'ignore)) (advice-add #'org-capture :around (lambda (fun &rest args) (letf! ((#'+org--restart-mode-h #'ignore)) (apply fun args)))) ;;(use-package! org-roam ;; :after org ;; :config ;; :init ;; (setq org-roam-directory "~/org/roam") ; No file-truename needed in Doom ;; :config ;; (advice-remove 'org-roam-db-query '+org-roam-try-init-db-a) ;; (org-roam-db-autosync-mode) ;; (setq org-roam-completion-everywhere t)) ; (use-package! org-roam ; :custom ; (org-roam-directory "~/org/roam") ; (org-roam-completion-everywhere t) ; (org-roam-capture-templates ; '(("d" "default" plain ; "%?" ; :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" ; "#+title: ${title}\n") ; :unnarrowed t) ; ("r" "reference" plain ; "%?" ; :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" ; "#+title: ${title}\n#+filetags: :reference:\n") ; :unnarrowed t) ; ("p" "project" plain ; "\n* Goals\n\n%?\n\n* Tasks\n\n* Notes\n\n" ; :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" ; "#+title: ${title}\n#+filetags: :project:\n") ; :unnarrowed t))) ; :config ; (org-roam-setup) ; ;; If using org-roam-protocol ; (require 'org-roam-protocol)) (after! org (require 'org-re-reveal) (setq org-re-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js") (setq org-re-reveal-theme "white") (setq org-re-reveal-transition "slide")) (after! org (require 'org-tempo) (add-to-list 'org-structure-template-alist '("n" . "notes"))) (use-package! anki-editor :after org :config (setq anki-editor-create-decks t) :bind (:map org-mode-map ("C-c a" . anki-editor-push-notes))) (use-package! org-anki :after org :config (setq org-anki-default-deck "Default") :bind (:map org-mode-map ("C-c n" . org-anki-sync-entry))) (setq-default show-trailing-whitespace t) (use-package! bnf-mode :mode "\\.bnf\\'" :config ;; Optional: Add any custom configuration here (setq bnf-mode-hook (lambda () ;; Enable line numbers (display-line-numbers-mode) ;; Enable auto-pairing of angle brackets (modify-syntax-entry ?< "(>" bnf-mode-syntax-table) (modify-syntax-entry ?> ")<" bnf-mode-syntax-table)))) (use-package! ebnf-mode :mode "\\.ebnf\\'" :config ;; Optional customizations: (setq ebnf-mode-indent-offset 4) ; Default is 8 spaces (setq ebnf-mode-indent-by-production t) ; Align with the '=' in productions (setq ebnf-mode-comment-char ?\;) ; Use ; for comments (setq ebnf-mode-eop-char ?\.)) ; Use . for end of production (use-package! nix-mode :mode "\\.nix\\'" :config ;; Function to check if we're in a nixpkgs repository (defun in-nixpkgs-repo-p () (when-let ((root (or (locate-dominating-file default-directory ".git") (vc-root-dir)))) (or (string-match-p "/nixpkgs/?$" root) (file-exists-p (expand-file-name "pkgs/top-level/all-packages.nix" root)) (file-exists-p (expand-file-name ".nixpkgs-version.json" root))))) ;; Set up format-all-mode to use our custom formatter selection (set-formatter! 'nixfmt '("nixfmt") :modes '(nix-mode)) (set-formatter! 'alejandra '("alejandra" "--quiet") :modes '(nix-mode)) ;; Add hooks to handle all formatting scenarios (add-hook! 'nix-mode-hook ;; Disable LSP formatting (setq-local +format-with-lsp nil) ;; Set formatter for format-all-mode (+format/buffer) (setq-local +format-with (if (in-nixpkgs-repo-p) 'nixfmt 'alejandra)) ;; Handle format-on-save (when (bound-and-true-p format-all-mode) (format-all-mode -1)) (add-hook! 'before-save-hook :local (when (eq major-mode 'nix-mode) (if (in-nixpkgs-repo-p) (format-all-buffer 'nixfmt) (format-all-buffer 'alejandra)))) ;; Override lsp-format-buffer (advice-add 'lsp-format-buffer :around (lambda (orig-fun &rest args) (if (eq major-mode 'nix-mode) (if (in-nixpkgs-repo-p) (format-all-buffer 'nixfmt) (format-all-buffer 'alejandra)) (apply orig-fun args)))))) ;; Enable format-on-save globally if desired (setq +format-on-save-enabled-modes '(nix-mode)) (use-package! llvm-ts-mode :mode "\\.ll\\'" ; LLVM IR files :mode "\\.td\\'" ; TableGen files :hook (llvm-ts-mode . tree-sitter-mode)) (after! tree-sitter (add-to-list 'tree-sitter-major-mode-language-alist '(llvm-ts-mode . llvm))) (after! lsp-clangd (setq lsp-clients-clangd-executable "clangd") (setq lsp-clients--clangd-default-executable "clangd") (setq lsp-clangd-binary-path "clangd")) (after! org (use-package! ob-mermaid :config (setq ob-mermaid-cli-path "mmdc")) ; Adjust path if needed ;; Add mermaid to org-babel languages (org-babel-do-load-languages 'org-babel-load-languages (append org-babel-load-languages '((mermaid . t))))) (after! org (setq-default org-download-image-dir "./images") (defun my/org-download-image-dir-setup () "Create and set org-download-image-dir relative to current org file." (let* ((current-file-dir (file-name-directory (buffer-file-name))) (image-dir (expand-file-name "images" current-file-dir))) (make-directory image-dir t) (setq-local org-download-image-dir image-dir))) (add-hook 'org-mode-hook #'my/org-download-image-dir-setup) (setq org-download-link-format "[[file:%s]]\n") (setq org-download-timestamp "%Y%m%d-%H%M%S_") (setq org-download-screenshot-method "maim -s %s") ) (setq gptel-model 'mixtral-8x7b-32768 gptel-backend (gptel-make-openai "OpenRouter" ;Any name you want :host "openrouter.ai" :endpoint "/api/v1/chat/completions" :stream t :key "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" ;can be a function that returns the key :models '(google/gemini-2.5-flash-preview-05-20 google/gemini-2.5-flash-preview-05-20:thinking anthropic/claude-sonnet-4 )))