diff --git a/init.el b/init.el index 03e8a97..9e8a24f 100644 --- a/init.el +++ b/init.el @@ -1,10 +1,1264 @@ -;; We need org in order to make use of the tangling functionality +;;; -*- lexical-binding: t -*- + +(defun tangle-init () + "If the current buffer is init.org the code-blocks are +tangled, and the tangled file is compiled." + (when (equal (buffer-file-name) + (expand-file-name (concat user-emacs-directory "init.org"))) + ;; Avoid running hooks when tangling. + (let ((prog-mode-hook nil)) + (org-babel-tangle) + ;; (byte-compile-file (concat user-emacs-directory "init.el")) + ))) + +(add-hook 'after-save-hook 'tangle-init) + +(setq gc-cons-percentage 0.6) +(setq read-process-output-max (* 1024 1024)) ;; 1mb + +(setq idle-update-delay 1.0) + +(dolist (mode + '(tool-bar-mode + scroll-bar-mode + menu-bar-mode + blink-cursor-mode)) + (funcall mode 0)) + +(setq ring-bell-function 'ignore + initial-scratch-message nil + inhibit-startup-message t + use-dialog-box nil) + +(defvar emacs-autosave-directory + (concat user-emacs-directory "autosaves/") + "This variable dictates where to put auto saves. It is set to a + directory called autosaves located wherever your .emacs.d/ is + located.") + +;; Sets all files to be backed up and auto saved in a single directory. +(setq backup-directory-alist + `((".*" . ,emacs-autosave-directory)) + auto-save-file-name-transforms + `((".*" ,emacs-autosave-directory t))) + +(defvar bootstrap-version) +(let ((bootstrap-file + (expand-file-name + "straight/repos/straight.el/bootstrap.el" + (or (bound-and-true-p straight-base-dir) + user-emacs-directory))) + (bootstrap-version 7)) + (unless (file-exists-p bootstrap-file) + (with-current-buffer + (url-retrieve-synchronously + "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el" + 'silent 'inhibit-cookies) + (goto-char (point-max)) + (eval-print-last-sexp))) + (load bootstrap-file nil 'nomessage)) + +(straight-use-package 'use-package) +(setq straight-use-package-by-default t) + +(use-package org + :straight (:type built-in)) + +(defvar local-lisp (concat user-emacs-directory "local-lisp/")) +(add-to-list 'load-path local-lisp) +(let ((default-directory local-lisp)) + (normal-top-level-add-subdirs-to-load-path)) + +(set-language-environment "UTF-8") +(delete-selection-mode t) ;; Replace selected text when yanking +(dirtrack-mode t) ;; Directory tracking in shell +(global-so-long-mode t) ;; Mitigate performance for long lines +(global-visual-line-mode t) ;; Break lines instead of truncating them +(global-auto-revert-mode t) ;; Revert buffers automatically when they change +(recentf-mode t) ;; Remember recently opened files +(savehist-mode t) ;; Remember minibuffer prompt history +(save-place-mode t) ;; Remember last cursor location in file +(show-paren-mode t) ;; Highlight matching parentheses + +(setq-default tab-width 4 + fill-column 80 + indent-tabs-mode nil) +(setq use-short-answers t) +(setq initial-major-mode 'org-mode) + +(use-package exec-path-from-shell + :straight t + :config + (when (daemonp) + (exec-path-from-shell-initialize))) + +(use-package keychain-environment + :straight t + :init + (keychain-refresh-environment)) + +(use-package keychain-environment + :straight t + :defer t + :config + (keychain-refresh-environment)) + +(defvar custom-bindings-map (make-keymap) + "A keymap for custom keybindings.") + +(define-minor-mode custom-bindings-mode + "A mode that activates custom keybindings." + :init-value t + :keymap custom-bindings-map) + +(add-to-list 'default-frame-alist '(internal-border-width . 8 )) +(set-fringe-mode 4) +(setq-default fringes-outside-margins 0) +(setq-default indicate-buffer-boundaries nil) +(setq-default indicate-empty-lines nil) +(set-face-attribute 'header-line t :inherit 'default) + +(use-package gruvbox-theme + :straight t) + +;; doom needs this somehow +(use-package all-the-icons + :straight t) +(use-package doom-themes + :straight t + :config + (setq doom-themes-enable-bold t + doom-themes-enable-italic t) + (doom-themes-org-config)) + +(defvar nemo/dark-theme 'gruvbox-dark-medium) +(defvar nemo/light-theme 'gruvbox-light-medium) + +(add-hook 'after-init-hook (lambda () (load-theme nemo/dark-theme t))) + +(defadvice load-theme + (before disable-before-load (theme &optional no-confirm no-enable) activate) + (mapc 'disable-theme custom-enabled-themes)) + +(defun nemo/set-light-theme () + "load the light theme." + (interactive) + (load-theme nemo/light-theme t)) + +(defun nemo/set-dark-theme () + "load the dark theme." + (interactive) + (load-theme nemo/dark-theme t)) + +(setq help-window-select t + help-window-keep-selected t) + +(defvar nemo/font-height-mono 110) +(defvar nemo/font-height-sans 120) + +(defun apply-if-gui (&rest action) + "apply ACTION if emacs is run in GUI context, regardless of daemonp or display-graphic-p" + (if (daemonp) + (add-hook 'after-make-frame-functions + (lambda (frame) + (select-frame frame) + (if (display-graphic-p frame) + (apply action)))) + (if (display-graphic-p) + (apply action)))) + + +(set-face-attribute 'default nil :font "monospace" :height nemo/font-height-mono) +(set-face-attribute 'fixed-pitch nil :font "monospace" :height nemo/font-height-mono) +(set-face-attribute 'variable-pitch nil :font "sans-serif" :height nemo/font-height-sans) + +;; (when (member "SF Mono" (font-family-list)) +;; (set-face-attribute 'default nil :font "SF Mono" :height nemo/font-height-mono) +;; (set-face-attribute 'fixed-pitch nil :family "SF Mono" :height nemo/font-height-mono)) +(when (member "SF Pro Text" (font-family-list)) + (set-face-attribute 'variable-pitch nil :family "SF Pro Text" :height nemo/font-height-sans)) + +(defvar nemo/nerd-fonts-font "Symbols Nerd Font") + +(defun nemo/set-fallback-fonts () + "Set fallback fonts for icons/symbols." + (set-fontset-font t nil (font-spec :height nemo/font-height-mono :font nemo/nerd-fonts-font)) + ) + +(apply-if-gui #'nemo/set-fallback-fonts) + +(use-package nerd-icons + :straight t) + +(use-package emojify + :straight t + :config + (when (member "Apple Color Emoji" (font-family-list)) + (set-fontset-font t 'symbol (font-spec :family "Apple Color Emoji") nil 'prepend))) + +(use-package mixed-pitch + :straight t + :hook ((org-mode . mixed-pitch-mode) + (LaTeX-mode . mixed-pitch-mode))) + +;; Mode line setup +(column-number-mode t) ;; Show current column number in mode line +(setq-default + mode-line-format + '((:propertize "λ" face mode-line-emphasis) + " " + mode-line-buffer-identification + " " + ; read-only or modified status + (:eval + (cond (buffer-read-only + (propertize "  " 'face 'mode-line-read-only-face)) + ((buffer-modified-p) + (propertize " 󰳻 " 'face 'mode-line-modified-face)) + (t "  " 'face 'mode-line))) + ; directory and buffer/file name + (:propertize (:eval (shorten-directory default-directory 30)) + face mode-line-folder-face) + (:propertize "%b" + face mode-line-filename-face) + ;; Version control info + (:eval (when-let (vc vc-mode) + ;; Use a pretty branch symbol in front of the branch name + (list (propertize " " 'face 'font-lock-keyword-face) + (propertize (substring vc 5) + 'face 'font-lock-doc-face)))) + + + " " + (:propertize mode-name) + (:propertize (length local-minor-modes)) + ; (global-mode-string global-mode-string) + (:eval (propertize + " " 'display + `((space :align-to + (- (+ right right-fringe right-margin) + ,(+ 1 (string-width "%p %4l:%c"))))))) + ;; Line and column numbers + mode-line-percent-position + " " + (:propertize "%4l:" face mode-line-position-face) + (:eval (propertize "%c" 'face + (if (>= (current-column) 80) + 'mode-line-80col-face + 'mode-line-position-face))) + )) + +;; Helper function +(defun shorten-directory (dir max-length) + "Show up to `max-length' characters of a directory name `dir'." + (let ((path (reverse (split-string (abbreviate-file-name dir) "/"))) + (output "")) + (when (and path (equal "" (car path))) + (setq path (cdr path))) + (while (and path (< (length output) (- max-length 4))) + (setq output (concat (car path) "/" output)) + (setq path (cdr path))) + (when path + (setq output (concat ".../" output))) + output)) + +;; Extra mode line faces +(make-face 'mode-line-read-only-face) +(make-face 'mode-line-modified-face) +(make-face 'mode-line-folder-face) +(make-face 'mode-line-filename-face) +(make-face 'mode-line-position-face) +(make-face 'mode-line-mode-face) +(make-face 'mode-line-80col-face) + +(set-face-attribute 'mode-line-read-only-face nil + :inherit 'mode-line-face + :foreground "#4271ae" + :box '(:line-width 2 :color "#4271ae")) +(set-face-attribute 'mode-line-modified-face nil + :inherit 'mode-line-face + :foreground "#c82829" + :background "#ffffff" + :box '(:line-width 2 :color "#c82829")) +(set-face-attribute 'mode-line-folder-face nil + :inherit 'mode-line-face + :foreground "gray60") +(set-face-attribute 'mode-line-filename-face nil + :inherit 'mode-line-face + :foreground "#eab700" + :weight 'bold) +(set-face-attribute 'mode-line-position-face nil + :inherit 'mode-line-face) +(set-face-attribute 'mode-line-mode-face nil + :inherit 'mode-line-face + :foreground "gray80") +(set-face-attribute 'mode-line-80col-face nil + :inherit 'mode-line-position-face + :foreground "black" :background "#eab700") + +(defconst nemo/leader-evil "SPC") +(defconst nemo/leader-global "C-c") +(defconst nemo/major-key "m") + +(defconst nemo/leader-major-evil (concat nemo/leader-evil " " nemo/major-key)) +(defconst nemo/leader-major-global (concat nemo/leader-global " " nemo/major-key)) + +(use-package general + :straight t + :config + (general-define-key + :states '(emacs normal) + :prefix-map 'nemo/leader-prefix-map + :prefix-command 'nemo/leader-prefix-command + :global-prefix nemo/leader-global + :prefix nemo/leader-evil) + (general-create-definer leader-def + :prefix-command 'nemo/leader-prefix-command + :prefix-map 'nemo/leader-prefix-map) + (general-create-definer leader-other-def + :states '(emacs normal) + :prefix-map 'nemo/leader-prefix-map + :prefix-command 'nemo/leader-prefix-command + :global-prefix nemo/leader-global + :prefix nemo/leader-evil + ) + (general-create-definer leader-major-def + :states '(emacs normal) + :global-prefix nemo/leader-global + :prefix nemo/leader-evil + ) + ;; magit uses with-editor-mode to spawn the git process + ;; in with the emacs client as the $EDITOR + (general-def '(emacs normal) 'with-editor-mode-map ",," 'with-editor-finish) + (leader-def + "" #'nemo/switch-to-last-buffer + "" #'completion-at-point + "d" #'duplicate-line + "gb" #'xref-go-back + "gf" #'xref-go-forward + "bk" #'switch-to-prev-buffer + "bp" #'switch-to-prev-buffer + "bj" #'switch-to-next-buffer + "bn" #'switch-to-next-buffer + "bb" #'consult-buffer + "bd" #'kill-current-buffer + "bs" #'scratch-buffer + "wd" #'delete-window + "wo" #'delete-other-windows + "ff" #'find-file + "fi" '("Edit init.org" . nemo/edit-init-org) + "fs" '("Save" . save-buffer) + "fr" '("rg" . consult-ripgrep) + "fR" '("rg in dir" . nemo/consult-ripgrep-dir) + ) + ) + +(use-package engine-mode + :straight t + :defer t + :config + (defengine duckduckgo + "https://duckduckgo.com/?q=%s" + :keybinding "g") + + (defengine twitter + "https://twitter.com/search?q=%s" + :keybinding "x") + + (defengine wikipedia + "https://www.wikipedia.org/search-redirect.php?language=en&go=Go&search=%s" + :keybinding "w" + :docstring "Searchin' the wikis.") + + (defengine wiktionary + "https://www.wikipedia.org/search-redirect.php?family=wiktionary&language=en&go=Go&search=%s" + :keybinding "d") + + (defengine wolfram-alpha + "https://www.wolframalpha.com/input/?i=%s") + + (defengine youtube + "https://www.youtube.com/results?aq=f&oq=&search_query=%s" + :keybinding "y") + (engine-mode t) + ) + +(use-package diff-hl + :straight t + :config + (global-diff-hl-mode)) + +(use-package magit + :straight t + :defer t + :general + (leader-def + "gSh" 'magit-status-here + "gs" #'magit-status + "gSb" 'magit-blame) + :config + (setq magit-mode-quit-window 'magit-restore-window-configuration + ediff-window-setup-function #'ediff-setup-windows-plain + ediff-merge-split-window-function #'split-window-horizontally + ;;magit-auto-revert-mode t + )) + +(use-package forge + :straight t + :after magit) + +(use-package which-key + :straight t + :config + (which-key-mode)) + +(use-package rainbow-delimiters + :straight t + :hook (prog-mode . rainbow-delimiters-mode)) + +(use-package evil + :straight t + :init + (setq evil-want-C-u-scroll t) + (setq evil-want-keybinding nil) + (setq evil-want-integration t) + (setq evil-undo-system 'undo-fu) + :config + (evil-mode 1) + +(leader-def + "wj" 'evil-window-down + "wk" 'evil-window-up + "wh" 'evil-window-left + "wl" 'evil-window-right + ) + +(defun nemo/evil-search-forward--push-xref + (&optional _regex-p _no-recursive-edit) + "push current marker to xref stack when forward searching." + (xref-push-marker-stack)) + +(advice-add #'evil-search-forward + :before #'nemo/evil-search-forward--push-xref + '((name . "evil-search-push-xref"))) + +) + +(use-package evil-surround + :straight t + :defer t + :config + (global-evil-surround-mode 1)) + +(use-package evil-collection + :after evil + :straight t + :init (setq evil-collection-key-blacklist '("C-c " "")) + :config + (evil-collection-init)) + +(use-package undo-fu + :straight t + :defer t) + +(use-package projectile + :straight t + :defer t + :general + (leader-def + "p" '(:keymap project-prefix-map :wk "Projectile") + ) + :config + (setq projectile-project-search-path '("~/code/")) + (projectile-mode)) + +(use-package ripgrep + :straight t + :defer t) + +(use-package rg + :straight t + :defer t) + + (use-package wgrep + :straight t + :defer t) + +(use-package vterm + :straight t) + +(defun nemo/abort-minibuffer-if-active () + "Abort the minibuffer if it is active." + (interactive) + (when (active-minibuffer-window) + (abort-recursive-edit))) + +(global-set-key (kbd "") 'nemo/abort-minibuffer-if-active) + +(use-package olivetti + :straight t + :defer t + ;; :bind (:map custom-bindings-map ("C-c o" . olivetti-mode)) + :hook (org-mode . olivetti-mode) + :hook (olivetti-mode-on . (lambda () (olivetti-set-width 88))) + :config + (setq olivetti-style t)) + +(use-package jinx + :straight t + :hook (emacs-startup . global-jinx-mode) + :bind (("M-$" . jinx-correct) + ("C-M-$" . jinx-languages)) + :config + (leader-def "Ss" 'jinx-correct) + (setq jinx-languages "en_GB dk_DK de_DE")) + +(use-package ispell + :straight t + :defer t + :config + (setq ispell-dictionary "en_GB")) + +(use-package auctex + :straight t + :hook + (LaTeX-mode . turn-on-prettify-symbols-mode) + (LaTeX-mode . reftex-mode) + ;; (LaTeX-mode . (lambda () (corfu-mode -1))) + ;; (LaTeX-mode . outline-minor-mode) + (LaTeX-mode . olivetti-mode) + :config + (setq TeX-view-program-selection '((output-pdf "PDF Tools")) + TeX-view-program-list '(("PDF Tools" TeX-pdf-tools-sync-view)) + TeX-source-correlate-start-server t)) + +(use-package pdf-tools + :straight t + :defer t + :mode ("\\.pdf\\'" . pdf-view-mode) + :config + (pdf-loader-install) + (setq-default pdf-view-display-size 'fit-height) + (setq pdf-view-continuous t) + (setq +latex-viewers '(pdf-tools)) + (leader-major-def + :keymaps 'pdf-view-mode-map + "g b" #'pdf-history-backward + "g f" #'pdf-history-forward) + (general-def :keymaps 'pdf-view-mode-map + "j" (lambda() (interactive) (pdf-view-scroll-up-or-next-page 20)) + "k" (lambda() (interactive) (pdf-view-scroll-down-or-previous-page 20))) + ) + +(use-package org + :straight (:type built-in) + :defer t + :hook (org-mode . variable-pitch-mode) + ;; I basically always want to be running =visual-line-mode= anyway, but certainly in org-mode. + :hook (org-mode . visual-line-mode) + :hook (org-mode . nemo/prettify-symbols-setup) + :general-config + (general-define-key + :prefix-map 'nemo/org-map + "i" '(:ignore t :which-key "Insert..") + "ih" '("Heading" . org-insert-heading) + "is" '("Subheading" . org-insert-subheading) + "ii" '("Item" . org-insert-item) + "ib" '("Block..". org-insert-structure-template) + "il" '("Link" . org-insert-link) + ) + (leader-major-def + :keymaps 'org-mode-map + "m" '(:keymap nemo/org-map :wk "Org") + ) + (general-def 'normal 'org-src-mode-map ",," 'org-edit-src-exit) + (general-def 'normal 'org-mode-map + "TAB" 'org-cycle + "RET" 'org-open-at-point) + :config + +(custom-set-faces + '(org-document-title ((t (:height 1.8)))) + '(outline-1 ((t (:height 1.35)))) + '(outline-2 ((t (:height 1.3)))) + '(outline-3 ((t (:height 1.2)))) + '(outline-4 ((t (:height 1.1)))) + '(outline-5 ((t (:height 1.1)))) + '(outline-6 ((t (:height 1.1)))) + '(outline-8 ((t (:height 1.1)))) + '(outline-9 ((t (:height 1.1))))) + +(setq org-startup-folded 'content) + +(setq org-startup-with-latex-preview t) + +(setq org-startup-with-inline-images t) + +(plist-put org-format-latex-options :scale 1.35) + +(setq org-adapt-indentation t + org-hide-leading-stars t + org-pretty-entities-include-sub-superscripts t + org-pretty-entities t) + +(setq org-src-fontify-natively t + org-src-tab-acts-natively t + org-edit-src-content-indentation 0) + +) + +(use-package ox-epub + :straight t) + +(use-package org-fragtog + :straight t + :hook (org-mode . org-fragtog-mode)) + +(use-package org-appear + :straight t + :commands (org-appear-mode) + :hook (org-mode . org-appear-mode) + :config + (setq org-hide-emphasis-markers t) + (setq org-appear-autoemphasis t ;; show /../ *..* =..= ~..~ tokens + org-appear-autolinks t ;; show link hyperlinks when editing + org-appear-autosubmarkers t)) ;; show _.._ and superscript markers + +(use-package org-modern + :straight t + :defer t + :after org + :hook (org-mode . org-modern-mode)) + +(defun nemo/prettify-symbols-setup () + ;; org-babel + (push '("#+BEGIN_SRC" . ?≫) prettify-symbols-alist) + (push '("#+END_SRC" . ?≫) prettify-symbols-alist) + (push '("#+begin_src" . ?≫) prettify-symbols-alist) + (push '("#+end_src" . ?≫) prettify-symbols-alist) + + (push '("#+BEGIN_QUOTE" . ?❝) prettify-symbols-alist) + (push '("#+END_QUOTE" . ?❞) prettify-symbols-alist) + + (prettify-symbols-mode)) + +(use-package svg-tag-mode + :straight t + :config + (setq svg-tag-tags + '((":TODO:" . ((lambda (tag) (svg-tag-make "TODO")))))) + ) + (require 'org) -;; Open the org-mode configuration -(find-file (concat user-emacs-directory "init.org")) -;; Tangle the file -(org-babel-tangle) -;; Load the tangled file -(load-file (concat user-emacs-directory "init.el")) -;; Byte-compile it -(byte-compile-file (concat user-emacs-directory "init.el")) + +(setq org-agenda-start-on-weekday nil + org-agenda-block-separator nil + org-agenda-remove-tags t) + +(use-package org-super-agenda + :straight t + :after org + :config + (org-super-agenda-mode)) + +(setq org-agenda-files (list "~/Shared/agenda.org" + "~/notes.org" + "~/projects.org")) + +(add-hook 'emacs-startup-hook + (lambda () (progn (org-agenda nil "a") + (delete-other-windows) + (olivetti-mode)))) + +(use-package move-text + :straight t + :defer t + :bind (("M-j" . move-text-down) + ("M-k" . move-text-up))) + +(use-package treemacs + :straight t + ;; hijack projectile prefix because they fit together + :general + (general-define-key + :prefix-map 'project-prefix-map + "t" '("Treemacs" . treemacs-select-window) + ) + :config + (setq treemacs-width 25) + ) + + +(use-package treemacs-evil + :after (treemacs evil) + :straight t) + +(use-package treemacs-projectile + :after (treemacs projectile) + :straight t) + +(use-package treemacs-icons-dired + :hook (dired-mode . treemacs-icons-dired-enable-once) + :straight t) + +(use-package treemacs-magit + :after (treemacs magit) + :straight t) + +(use-package vertico + :straight t + :bind (:map minibuffer-local-map + ("C-h" . backward-kill-sexp)) + :config + (vertico-mode 1) + (setq vertico-count 25 + completion-ignore-case t + read-buffer-completion-ignore-case t + read-file-name-completion-ignore-case t) + (vertico-multiform-mode) + ) + +(use-package vertico-posframe + :straight t + ;; Ensure posframe is always restored when exiting a minibuffer + :hook (minibuffer-exit . (lambda () (vertico-posframe-mode 1))) + :config + (vertico-posframe-mode 1) + (setq vertico-posframe-height vertico-count + vertico-multiform-commands + '((consult-line (:not posframe)) + (consult-ripgrep (:not posframe)) + (nemo/consult-ripgrep (:not posframe)) + (nemo/consult-ripgrep-dir (:not posframe)) + (lsp-find-references (:not posframe)) + (embark-act (:not posframe)) + (t posframe)) + )) + +(use-package savehist + :straight t + :init (savehist-mode)) + +(use-package consult + :straight t + :bind (:map custom-bindings-map + ("C-x b" . consult-buffer) + ("M-g g" . consult-goto-line)) + :init + (setq xref-show-xrefs-function #'consult-xref + xref-show-definitions-function #'consult-xref) + :config + ()) + +(defun nemo/exec-without-posframe (fn &rest args) + "Execute FN with ARGS while temporarily disabling vertico-posframe-mode." + (vertico-posframe-mode -1) + (unwind-protect + (apply fn args) + (vertico-posframe-mode 1))) + +(defun nemo/consult-line () + (interactive) + (nemo/exec-without-posframe #'consult-line)) + +(defun nemo/consult-ripgrep (&rest args) + (interactive) + (apply #'consult-ripgrep args)) + +(defun nemo/consult-ripgrep-dir () + "Call consult-ripgrep in a user-specified directory." + (interactive) + (let ((dir (read-directory-name "Ripgrep directory: "))) + (consult-ripgrep dir)) + ) + +(bind-key "C-s" 'consult-line custom-bindings-map) +(bind-key "C-M-s" 'consult-ripgrep custom-bindings-map) + +(use-package marginalia + :straight t + :init + (marginalia-mode 1)) + +(use-package corfu + :straight t + :hook ((prog-mode text-mode) . completion-preview-mode) + :custom + ;; Enable auto completion + (corfu-auto t) + ;; Enable cycling for `corfu-next/previous' + (corfu-cycle t) + ;; No delay + (corfu-auto-delay 0) + ;; Start when this many characters have been typed + (corfu-auto-prefix 1) + ;; Short delay + (corfu-popupinfo-delay 0.5) + ;; Preselect the first suggestion + (corfu-preselect nil) + (corfu-on-exact-match nil) + ;; Don't automatically fill in the selected candidate + (corfu-preview-current nil) + :custom + (lsp-completion-provider :none) + :init + (defun nemo/orderless-dispatch-flex-first (_pattern index _total) + (and (eq index 0) 'orderless-flex)) + + (defun nemo/lsp-mode-setup-completion () + (setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults)) '(orderless)) + (add-hook 'orderless-style-dispatchers #'nemo/orderless-dispatch-flex-first nil 'local)) + :hook (lsp-completion-mode . nemo/lsp-mode-setup-completion) + :config + (global-corfu-mode)) + +(use-package corfu-terminal + :straight t + :defer t + :hook (before-make-frame . + (lambda () + (corfu-terminal-mode + (if (display-graphic-p) -1 +1)))) + ) + +;; (use-package emacs +;; ;; :custom +;; ;; TODO +;; :init +;; ;; TAB cycle if there are only few candidates +;; ;; (setq completion-cycle-threshold 3) + +;; (setq enable-recursive-minibuffers t) +;; ;; Hide commands in M-x which do not apply to the current mode. Corfu +;; ;; commands are hidden, since they are not supposed to be used via M-x. +;; (setq read-extended-command-predicate +;; #'command-completion-default-include-p) + +;; (setq text-mode-ispell-word-completion nil) + +;; ;; Enable indentation+completion using the TAB key. +;; ;; `completion-at-point' is often bound to M-TAB. +;; (setq tab-always-indent 'complete) +;; ) + +(use-package kind-icon + :straight t + :after corfu + :config + (add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter)) + +(use-package cape + :straight t + ;; Bind dedicated completion commands + ;; Alternative prefix keys: C-c p, M-p, M-+, ... + ;; :bind (("C-c p p" . completion-at-point) ;; capf + ;; ("C-c p t" . complete-tag) ;; etags + ;; ("C-c p d" . cape-dabbrev) ;; or dabbrev-completion + ;; ("C-c p h" . cape-history) + ;; ("C-c p f" . cape-file) + ;; ("C-c p k" . cape-keyword) + ;; ("C-c p s" . cape-symbol) + ;; ("C-c p a" . cape-abbrev) + ;; ("C-c p l" . cape-line) + ;; ("C-c p w" . cape-dict) + ;; ("C-c p \\" . cape-tex) + ;; ("C-c p _" . cape-tex) + ;; ("C-c p ^" . cape-tex) + ;; ("C-c p &" . cape-sgml) + ;; ("C-c p r" . cape-rfc1345)) + :init + ;; Add `completion-at-point-functions', used by `completion-at-point'. + ;; NOTE: The order matters! + ;; (add-to-list 'completion-at-point-functions #'cape-capf-buster) + ;; (add-to-list 'completion-at-point-functions #'cape-dabbrev) + ;; (add-to-list 'completion-at-point-functions #'cape-file) + ;; (add-to-list 'completion-at-point-functions #'cape-elisp-block) + ;; (add-to-list 'completion-at-point-functions #'cape-history) + ;; (add-to-list 'completion-at-point-functions #'cape-keyword) + ;; (add-to-list 'completion-at-point-functions #'cape-tex) + ;; (add-to-list 'completion-at-point-functions #'cape-dict) + ;; (add-to-list 'completion-at-point-functions #'cape-sgml) + ;; (add-to-list 'completion-at-point-functions #'cape-rfc1345) + ;; (add-to-list 'completion-at-point-functions #'cape-abbrev) + ;; (add-to-list 'completion-at-point-functions #'cape-symbol) + ;; (add-to-list 'completion-at-point-functions #'cape-line) + ) + +(use-package prescient + :straight t + :config + (add-to-list 'completion-styles 'prescient) + (add-to-list 'prescient-filter-method 'fuzzy)) + +(use-package orderless + :straight t + :config + (add-to-list 'completion-styles 'orderless) + (setq orderless-matching-styles '(orderless-flex) + completion-category-overrides '((file (styles basic partial-completion))) + orderless-component-separator "[ |]") + ) + +(add-hook 'prog-mode-hook 'hs-minor-mode) + +(use-package inheritenv + :straight t) + +(use-package envrc + :straight t + :hook (after-init . envrc-global-mode)) + +(use-package hl-todo + :straight t + :hook ((prog-mode) . hl-todo-mode) + :config + (setq hl-todo-keyword-faces + '(("TODO" . "#e78a4e"))) + ) + +(use-package copilot + :straight (:host github :repo "copilot-emacs/copilot.el" :files ("*.el")) + :ensure t + :hook ((prog-mode markdown-mode conf-toml-mode) . copilot-mode) + :bind ( + ("TAB" . 'copilot-accept-completion) + ("C-" . 'copilot-accept-completion) + ("M-" . 'copilot-accept-completion-by-word) + ("C-S-" . 'copilot-accept-completion-by-line) + ) + ) + +(use-package copilot-chat + :straight (:host github :repo "chep/copilot-chat.el" :files ("*.el")) + :after (org markdown-mode) + :general + (leader-def + "cg" '("Generate commit message" . copilot-chat-insert-commit-message) + "cG" '("Regenerate commit message" . copilot-chat-regenerate-commit-message) + "cC" '("Open Copilot Chat" . copilot-chat-display) + "cba" '("Add Buffer to Copilot" . copilot-chat-add-current-buffer) + "cbd" '("Remove Buffer from Copilot" . copilot-chat-del-current-buffer) + "cbw" '("Add Workspace to Copilot" . copilot-chat-add-workspace) + "cbf" #'copilot-chat-add-file + "cbb" '("List Buffers visible to Copilot" . copilot-chat-list) + "cch" #'copilot-chat-hide + "ccx" #'copilot-chat-reset + "ccb" #'copilot-chat-switch-to-buffer + "ccd" #'copilot-chat-doc + "ccr" #'copilot-chat-review + "ccm" #'copilot-chat-set-model + "cy" '("Past latest code block" . copilot-chat-yank) + ) + ) + +(use-package smartparens + :straight t + :hook ((prog-mode text-mode markdown-mode) . smartparens-mode) + :config + (require 'smartparens-config)) + +(use-package flycheck + :straight t + :defer t + :hook (after-init. global-flycheck-mode) + :config) + +(use-package yasnippet + :straight t + :defer t + :hook ((prog-mode text-mode) . yas-minor-mode)) + +(use-package yasnippet-snippets + :straight t) + +(use-package lsp-mode + :straight t + :defer t + :hook (prog-mode . lsp-deferred) + :hook (lsp-mode . lsp-enable-which-key-integration) + :hook (lsp-mode . lsp-inlay-hints-mode) + :init + (setq lsp-keymap-prefix "C-l") + (add-to-list 'completion-at-point-functions #'lsp-completion-at-point) + ;; (advice-add 'lsp :before #'envrc-reload) + :commands lsp + :general-config + (leader-def + "l" '(:keymap lsp-command-map :wk "LSP") + ) + :config + (setq + lsp-idle-delay 0.5 + lsp-inlay-hint-enable t + lsp-modeline-code-actions-enable t + lsp-modeline-code-actions-segments '(name count) + lsp-modeline-diagnostics-enable t + lsp-completion-enable-additional-text-edit t + + lsp-completion-provider :capf + lsp-enable-snippet t + + lsp-rust-server 'rust-analyzer + lsp-rust-analyzer-server-display-inlay-hints t + lsp-rust-analyzer-proc-macro-enable t + lsp-rust-analyzer-completion-auto-import-enable t + lsp-rust-analyzer-proc-macro-enable t + lsp-rust-analyzer-binding-mode-hints t + lsp-rust-analyzer-display-closure-return-type-hints t + lsp-rust-analyzer-server-format-inlay-hints t + lsp-rust-analyzer-cargo-extra-env ["RUSTFLAGS", "-Clinker=clang -Clink-arg=-fuse-ld=mold"] + + lsp-enable-suggest-server-download nil) + + (setq lsp-glsl-executable '("glsl_analyzer")) + (add-to-list 'lsp-language-id-configuration '("CMakeLists.txt" . "cmake")) + ) + +(use-package consult-lsp + :straight t + :general + (with-eval-after-load 'lsp-mode + (general-define-key + :keymaps 'lsp-command-map + "c s" '("Symbols" . consult-lsp-symbols) + "c f" '("Symbols" . consult-lsp-file-symbols) + "c d" '("Diagnostics" . consult-lsp-diagnostics) + ) + ) + ) + +(use-package lsp-treemacs + :straight t + :commands lsp-treemacs-errors-list) + +(use-package lsp-ui + :config + (setq + ;; lsp-modeline-code-actions-enable nil + ;; lsp-rust-analyzer-cargo-all-targets nil + ;; lsp-rust-analyzer-server-command "xwin-env rust-analyzer" + lsp-ui-sideline-show-code-actions t + lsp-ui-doc-enable t + lsp-ui-doc-delay 0.5 + lsp-ui-doc-show-with-cursor t + ; lsp-ui-doc-use-childframe t + ; lsp-ui-doc-use-webkit t + ) + :commands lsp-ui-mode) + +(defvar-local nemo/lsp-format-on-save t) + +(define-minor-mode nemo/lsp-format-on-save-mode + "Run lsp-format-buffer on save." + :lighter " fmt" + (if nemo/lsp-format-on-save-mode + (add-hook 'before-save-hook #'lsp-format-buffer nil t) + (remove-hook 'before-save-hook #'lsp-format-buffer nil t) + )) + +(defun nemo/do-lsp-format-on-save () + "Format on save using LSP server." + (if nemo/lsp-format-on-save + (lsp-format-buffer))) + +(use-package wgsl-mode + :straight t + :ensure lsp-mode + :mode "\\.wesl\\'" + :hook (wgsl-mode . lsp-deferred) + :init + (add-to-list 'lsp-language-id-configuration '(wgsl-mode . "wgsl")) + (lsp-register-client (make-lsp-client + :new-connection (lsp-stdio-connection "wgsl-analyzer") + :activation-fn (lsp-activate-on "wgsl") + :server-id 'wgsl-analyzer)) + ) + +(use-package glsl-mode + :straight t + :defer t + :init + (add-to-list 'auto-mode-alist '("\\.vert\\'" . glsl-mode)) + (add-to-list 'auto-mode-alist '("\\.glsl\\'" . glsl-mode)) + (add-to-list 'auto-mode-alist '("\\.frag\\'" . glsl-mode)) + ) + +(require 'hlsl-mode) +(with-eval-after-load 'hlsl-mode + (add-to-list 'auto-mode-alist '("\\.hlsl\\'" . hlsl-mode)) + (add-to-list 'auto-mode-alist '("\\.frag\\'" . hlsl-mode)) + ) + +(require 'slang-ts-mode) +(add-hook 'slang-ts-mode-hook (lambda () (hs-minor-mode -1))) + +;; (use-package rust-mode +;; :straight t +;; ;; :hook (rust-mode . lsp-mode) +;; :init +;; (setq rust-mode-treesitter-derive t +;; )) + +(use-package rustic + :straight t + :defer t + :after (inheritenv envrc) + ;; :after (rust-mode) + :hook(rustic-mode . nemo/lsp-format-on-save-mode) + :general-config + (general-define-key + :prefix-map 'nemo/rust-map + "c v" '("Check" . rustic-cargo-check) + "c c" '("Compile" . rustic-compile) + "c b" '("Build" . rustic-cargo-build) + ;;"c B" '("Build" . rust-cargo-relea) + "c c" '("Clean" . rustic-cargo-clean) + "c x" '("Run" . rustic-cargo-run) + "c f" '("Format Buffer" . rustic-format-buffer) + "t t" '("Current Test" . rustic-cargo-current-test) + "t a" '("Test" . rustic-cargo-test) + "c a" '("cargo-add" . rustic-cargo-add) + "c r" '("cargo-rm" . rustic-cargo-remove) + "c l" '("lint" . rustic-cargo-clippy) + "c L" '("lint" . rustic-cargo-clippy-fix) + "c n" '("new" . rustic-cargo-new) + "c i" '("init" . rustic-cargo-init) + "c d" '("Docs" . rustic-cargo-doc) + ) + (leader-major-def + :keymaps 'rustic-mode-map + "m" '(:keymap nemo/rust-map :wk "Cargo") + ) + :config + (setq rust-mode-treesitter-derive t + rustic-format-on-save nil + ;; rustic-format-trigger 'on-save + ;; rustic-format-on-save-method #'rustic-format-buffer + ;; rustic-analyzer-command '("/usr/bin/rust-analyzer") + ) + ;; (setq nemo/lsp-format-on-save t) + ) + +(use-package rust-playground + :straight t + :defer t) + +(use-package dap-mode + :straight t + :after (lsp-mode) + :config + ;; (require 'dap-cpptools) + ;; (dap-cpptools-setup) + (require 'dap-gdb-lldb) + (dap-register-debug-template "Rust::GDB Run Configuration" + (list :type "gdb" + :request "launch" + :name "GDB::Run" + :gdbpath "rust-gdb" + :target nil + :cwd nil)) + (dap-auto-configure-mode)) + +(use-package web-mode + :straight t + :defer t + :mode + (("\\.phtml\\'" . web-mode) + ("\\.tpl\\.php\\'" . web-mode) + ("\\.twig\\'" . web-mode) + ("\\.xml\\'" . web-mode) + ("\\.html\\'" . web-mode) + ("\\.htm\\'" . web-mode) + ("\\.[gj]sp\\'" . web-mode) + ("\\.as[cp]x?\\'" . web-mode) + ("\\.eex\\'" . web-mode) + ("\\.erb\\'" . web-mode) + ("\\.mustache\\'" . web-mode) + ("\\.handlebars\\'" . web-mode) + ("\\.hbs\\'" . web-mode) + ("\\.eco\\'" . web-mode) + ("\\.ejs\\'" . web-mode) + ("\\.svelte\\'" . web-mode) + ("\\.ctp\\'" . web-mode) + ("\\.djhtml\\'" . web-mode)) + :config + (setq + web-mode-css-indent-offset 2 + web-mode-code-indent-offset 2 + web-mode-attr-indent-offset 2 + web-mode-markup-indent-offset 2)) + +(use-package clang-format + :straight t + :defer t) + +(use-package cmake-mode + :straight t) + +(use-package zig-mode + :straight t + :config + (add-to-list 'auto-mode-alist '("\\.zig\\'" . zig-mode)) + (setq lsp-zig-enable-build-on-save t + lsp-zig-enable-inlay-hints nil + lsp-zig-build-on-save-step "check")) + +(use-package nix-mode + :ensure t + :mode ("\\.nix\\'" "\\.nix.in\\'") + ) + +(defun snake-case () + "convert region from PascalCase into snake_case" + (interactive) + (save-excursion + (let ((bounds (bounds-of-thing-at-point 'symbol))) + (replace-regexp "\\([A-Z]\\)" "_\\1" nil (1+ (car bounds)) (cdr bounds)) + (downcase-region (car bounds) (cdr (bounds-of-thing-at-point 'word))))) + ) + +(defun nemo/edit-init-org () + "Open the init.org file." + (interactive) + (find-file (concat user-emacs-directory "/init.org")) + ) + +(defun nemo/magit-dotfiles () + "View Dotfiles repository with magit" + (interactive) + (require 'magit) + (let ((magit-git-global-arguments + `(,(substitute-env-vars "--git-dir=$HOME/.cfg") + ,(substitute-env-vars "--work-tree=$HOME") + ,@magit-git-global-arguments))) + (magit-status "~") + (recursive-edit))) + +(set-default 'tramp-default-proxies-alist (quote ((".*" "\\`root\\'" "/ssh:%h:")))) +(require 'tramp) + +(defun sudo-edit-current-file () + (interactive) + (let ((position (point))) + (find-alternate-file + (if (file-remote-p (buffer-file-name)) + (let ((vec (tramp-dissect-file-name (buffer-file-name)))) + (tramp-make-tramp-file-name + "sudo" + (tramp-file-name-user vec) + (tramp-file-name-host vec) + (tramp-file-name-localname vec))) + (concat "/sudo:root@localhost:" (buffer-file-name)))) + (goto-char position))) +(leader-def "fe" 'sudo-edit-current-file) + +(defun nemo/switch-to-last-buffer () + (interactive) + (switch-to-buffer nil) + ) + +(define-key custom-bindings-map (kbd "C-c l") 'org-store-link) +(define-key custom-bindings-map (kbd "C-c a") 'org-agenda) +(define-key custom-bindings-map (kbd "C-c c") 'org-capture) +(define-key custom-bindings-map (kbd "C-c t") 'org-todo) +(define-key custom-bindings-map (kbd "M-h") 'org-todo) diff --git a/init.org b/init.org index f33336c..bbd080f 100644 --- a/init.org +++ b/init.org @@ -1603,7 +1603,7 @@ LSP sets it's prefix key to =s-l= by default, which uses the Super key which I u :init (setq lsp-keymap-prefix "C-l") (add-to-list 'completion-at-point-functions #'lsp-completion-at-point) - (advice-add 'lsp :before #'envrc-reload) + ;; (advice-add 'lsp :before #'envrc-reload) :commands lsp :general-config (leader-def @@ -1629,6 +1629,7 @@ LSP sets it's prefix key to =s-l= by default, which uses the Super key which I u lsp-rust-analyzer-binding-mode-hints t lsp-rust-analyzer-display-closure-return-type-hints t lsp-rust-analyzer-server-format-inlay-hints t + lsp-rust-analyzer-cargo-extra-env ["RUSTFLAGS", "-Clinker=clang -Clink-arg=-fuse-ld=mold"] lsp-enable-suggest-server-download nil)