- Bootstrap
- Gui
- Editor
- Org mode
- RSS
- Selectrum
- [[#mail-wanderlust][Mail [Wanderlust]]]
- LSP
- Rust
- Lean4
- Magit
- Consult
- EMMS
- Transient
- Work
- Misc
- Keybinds
(setq user-full-name "Valdemar Erk"
user-mail-address "[email protected]")
;; Get pin-code popup in emacs.
(setq epa-pinentry-mode 'loopback)
(setq epg-pinentry-mode 'loopback)
;; If there is a Yubikey use it.
(if (< 0 (length (shell-command-to-string "ykman list")))
(setq auth-sources '("~/.authinfo.gpg"))
(setq auth-sources '("~/.authinfo")))
(setq custom-file "~/.emacs-custom.el")
(if (file-readable-p custom-file)
(load custom-file))
(set-language-environment "UTF-8")
(setq
backup-by-copying t ; don't clobber symlinks
backup-directory-alist '(("." . "~/.saves/")) ; don't litter my fs tree
delete-old-versions t
kept-new-versions 8
kept-old-versions 8
version-control t) ; use versioned backups
;; Danish calender
(load-file "~/.emacs.d/lisp/da-kalender.el")
(setq exec-path (append exec-path '("/home/erk/.cargo/bin")))
; https://tobytripp.github.io/emacs.d/mail-in-emacs.html
(defun erk/auth-info (&rest search-spec)
"Given a LOGIN to search for, return `auth-sources' that match.
Valid search keys are:
- :user
- :host
- :port
Setting :max will have no result as this function only returns a
single result. If there are multiple matches, the first will be
returned.
Results are returned as an alist with the `:secret' property
pre-evaluated."
(dolist (default '((:max . 1) (:require . (:secret))))
(plist-put search-spec (car default) (cdr default)))
(let ((entry (nth 0 (apply 'auth-source-search search-spec))))
(mapcar (lambda (e)
(let ((prop (car e))
(value (if (functionp (cadr e))
(funcall (cadr e))
(cadr e))))
(cons prop value)))
(seq-partition entry 2))))
Set up some small things to start with:
;; Turn off start screen.
(setq inhibit-startup-screen t)
;; Turn off tool-bar-mode.
(when (fboundp 'tool-bar-mode)
(tool-bar-mode -1))
;; Turn off the menu bar.
(menu-bar-mode -1)
;; Don't blink the cursor.
(blink-cursor-mode -1)
;; enable column-number-mode.
(column-number-mode 1)
;; Remove the scroll bar.
(scroll-bar-mode -1)
;; Fix strange size issues with tiling wms
(setq frame-resize-pixelwise t)
Set up scrolling
;; makes scrolling a bit less jumpy.
(setq mouse-wheel-follow-mouse t ;; scroll window under mouse
scroll-step 1 ;; keyboard scroll one line at a time
mouse-wheel-progressive-speed nil ;; don't accelerate scrollin
mouse-wheel-scroll-amount '(1 ((shift) . 1))) ;; one line at a time
Set up some ansi colours.
;(setq ansi-color-faces-vector
; [default default default italic underline success warning error])
Clean up the mode-line
(straight-use-package 'blackout)
(blackout 'tree-sitter-mode)
(blackout 'global-tree-sitter-mode)
(blackout 'tree-sitter-hl-mode)
(blackout 'goggles-mode)
(blackout 'editorconfig-mode)
(blackout 'yas-minor-mode)
;; Installer ikoner
(straight-use-package 'all-the-icons)
;; Installer doom-modeline
;; (use-package doom-modeline
;; :ensure t
;; :init (doom-modeline-mode 1))
We start by setting the paren mode to blocks:
(show-paren-mode t)
;; (setq show-paren-style 'expression)
(use-package moe-theme)
;; Show highlighted buffer-id as decoration. (Default: nil)
(setq moe-theme-highlight-buffer-id t)
;; Resize titles (optional).
(setq moe-theme-resize-title-markdown '(1.5 1.4 1.3 1.2 1.0 1.0))
(setq moe-theme-resize-title-org '(1.5 1.4 1.3 1.2 1.1 1.0 1.0 1.0 1.0))
(setq moe-theme-resize-title-rst '(1.5 1.4 1.3 1.2 1.1 1.0))
;; Choose a color for modeline.(Default: blue)
(setq moe-theme-modeline-color 'cyan)
;; Finally, apply moe-theme now.
;; Choose what you like, (moe-light) or (moe-dark)
(moe-dark)
(custom-theme-set-faces
'moe-dark
'(tree-sitter-hl-face:comment ((,class (:background unspecified :foreground ,moe-dark-comment :slant italic)))))
Set up fonts
(add-to-list 'initial-frame-alist '(font-backend . (harfbuzz)))
(add-to-list 'default-frame-alist '(font-backend . (harfbuzz)))
(defvar erk/font "Cascadia Code PL SemiLight-13" "Default font")
;; Berkerley Mono
(setq erk/font "Berkeley Mono-10:style=Regular")
;; This is done in a slightly odd way to ensure it is set when
;; starting from deamon mode.
(set-frame-font erk/font nil t)
;; (set-face-attribute 'default nil :height 140)
;; (defun fontify-frame (frame)
;; (set-frame-parameter frame 'font erk/font))
;; Fontify current frame
;(fontify-frame nil)
;; Fontify any future frames
;; (push 'fontify-frame after-make-frame-functions)
;; (add-hook 'after-make-frame-functions
;; `(lambda (frame)
;; (select-frame frame)
;; (when (display-graphic-p frame)
;; (set-frame-font erk/font))))
;; (set-face-attribute 'default nil :height 140)
;; (when (member "Twemoji" (font-family-list))
;; (set-fontset-font
;; t 'symbol (font-spec :family "Twemoji") nil 'prepend))
;; (setq lsp-semantic-token-faces
;; '(("variable.reference" . (t (:inherit lsp-face-semhl-variable :slant italic)))
;; ("parameter.reference" . (t (inherit lsp-face-semhl-parameter :slant italic)))
;; ("method.static" . (t (:inherit lsp-face-semhl-method :foreground "#f0c506")))
;; ("method.public" . (t (:inherit lsp-face-semhl-method :foreground "#eedf54")))
;; ("method.library" . (t (:inherit lsp-face-semhl-method :foreground "#a5cf0a")))
;; ("method.library.static" . (t (:inherit lsp-face-semhl-method :foreground "#f0c506")))
;; ("method.trait" . (t (:inherit lsp-face-semhl-method :foreground "#cca34a")))
;; ("method.library.trait" . (t (:inherit lsp-face-semhl-method :foreground "#d1ce08")))
;; ("keyword.unsafe" . (t (:inherit lsp-face-semhl-keyword :foreground "#df732b" :slant italic)))
;; ("lifetime" . (t (:inherit tree-sitter-hl-face:label :foreground "#11ddcc")))
;; ("method.static.unsafe" . (t (:inherit lsp-face-semhl-method :foreground "#df732b")))
;; ("method.declaration.unsafe" . (t (:inherit lsp-face-semhl-method :foreground "#df732b")))
;; ("*.unsafe" . (t (:inherit lsp-face-semhl-method :foreground "#df732b" :slant italic)))
;; ("method.library.unsafe" . (t (:inherit lsp-face-semhl-method :foreground "#df732b")))
;; ("interface.library" . (t (:inherit lsp-face-semhl-interface :foreground "#8ec03e")))
;; ("generic.attribute" . (t (:inherit tree-sitter-hl-face:attribute :foreground "#fdf9287e")))
;; ("attribute.attribute" . (t (:inherit tree-sitter-hl-face:attribute :foreground "#8ec03e7e")))
;; ("parenthesis.attribute" . (t (:inherit tree-sitter-hl-face:attribute :foreground "#338d63")))
;; ("typeParameter" . (t (:inherit tree-sitter-hl-face:type.argument :foreground "#ca90fa" :weight bold)))
;; ("selfKeyword" . (t (:inherit lsp-face-semhl-keyword :foreground "#809dff")))
;; ("enum" . (t (:inherit lsp-face-semhl-keyword :foreground "#17b1d8")))
;; ("property" . (t (:inherit lsp-face-semhl-keyword :foreground "#75bfe7" :slant italic)))
;; ("parameter" . (t (:inherit lsp-face-semhl-parameter :foreground "#00afce")))
;; ("*.consuming" . (t (:inherit lsp-face-semhl-keyword :foreground :weight bold)))
;; ("namespace" . (t (:inherit lsp-face-semhl-namespace :foreground "#99bfc4")))
;; ("namespace.library" . (t (:inherit lsp-face-semhl-namespace :foreground "#b4c499")))
;; ("unresolvedReference" . (t (:inherit lsp-face-semhl-keyword :foreground "#ff493c" :slant italic)))
;; ("operator" . (t (:inherit tree-sitter-hl-face:operator :foreground "#d4d4d4da")))
;; ("comma" . (t (:inherit tree-sitter-hl-face:punctuation.delimiter :foreground "#d4d4d4da")))
;; ("colon" . (t (:inherit tree-sitter-hl-face:punctuation.delimiter :foreground "#d4d4d4da")))
;; ("semicolon" . (t (:inherit tree-sitter-hl-face:punctuation.delimiter :foreground "#d4d4d4da")))
;; ("punctuation" . (t (:inherit tree-sitter-hl-face:punctuation.delimiter :foreground "#d4d4d4da")))
;; ("brace" . (t (:inherit tree-sitter-hl-face:punctuation.bracket :foreground "#f0ddddda")))
;; ("parenthesis" . (t (:inherit tree-sitter-hl-face:punctuation :foreground "#d4d4d4da")))
;; ("builtinType" . (t (:inherit tree-sitter-hl-face:type.builtin :foreground "#b7fc89cb")))
;; ("angle" . (t (:inherit tree-sitter-hl-face:punctuation :foreground "#d4d4d4da")))
;; ("operator.controlFlow" . (t (:inherit tree-sitter-hl-face:operator :foreground "#fd8b5d")))
;; ("interface" . (t (:inherit lsp-face-semhl-interface :foreground "#f7ae40")))
;; ("typeAlias.trait" . (t (:inherit lsp-face-semhl-interface :foreground "#f1e6a3")))
;; ("keyword.controlFlow" . (t (:inherit lsp-face-semhl-keyword :foreground "#e689bc")))
;; ("keyword.async" . (t (:inherit lsp-face-semhl-keyword :foreground "#ca99f8")))
;; ("keyword.async.controlFlow" . (t (:inherit lsp-face-semhl-keyword :foreground "#ca99f8")))
;; ("macro" . (t (:inherit lsp-face-semhl-keyword :foreground "#c0b5ff")))
;; ("boolean" . (t (:inherit tree-sitter-hl-face:constant.builtin :foreground "#14b16f")))
;; ("string" . (t (:inherit lsp-face-semhl-string :foreground "#e98e6a")))))
(use-package goggles
:hook ((prog-mode text-mode) . goggles-mode)
:config
(setq-default goggles-pulse t))
Indent with spaces
(setq-default indent-tabs-mode nil)
(setq indent-tabs-mode nil)
Install rainbow delimiters
(use-package rainbow-delimiters)
(add-hook 'prog-mode-hook #'rainbow-delimiters-mode)
Install multiple-cursors, the keybinds are in the last chapter
(use-package multiple-cursors)
(use-package editorconfig
:blackout
:ensure t
:config
(editorconfig-mode 1))
(use-package parinfer-rust-mode
:hook emacs-lisp-mode
:init
(setq parinfer-rust-auto-download t))
(use-package yasnippet
:ensure t)
(yas-reload-all)
Will have to be cleaned up!
(use-package org-contrib
:ensure t)
(setq org-src-preserve-indentation t
org-edit-src-content-indentation 0)
;; (use-package org-ref
;; :ensure t)
;; (use-package org-superstar
;; :ensure t)
(use-package toc-org
:ensure t
:init
(add-hook 'org-mode-hook #'toc-org-mode))
;; (use-package auctex
;; :ensure t)
;; (use-package cdlatex
;; :ensure t)
;; (require 'org-ref
;; 'org-superstar)
(straight-use-package 'ox-gfm)
(org-babel-do-load-languages
'org-babel-load-languages
'((plantuml . t)))
;; (org-babel-do-load-languages 'org-babel-load-languages
;; '((shell . t)
;; (latex . t)
;; (python . t)))
;; (require 'org)
;; (require 'ob-dot)
;; (setq org-log-done t)
;; (setq org-agenda-files (list "~/org/todo.org" "~/org/Kalender/Personlig.org"))
(setq org-agenda-files (list "~/org/nerve.org"))
;; (setq org-latex-default-figure-position "H")
;; (setq org-src-fontify-natively t)
;; (setq org-latex-listings 'minted)
;; (setq org-latex-minted-options
;; '(("frame" "lines")
;; ("linenos=true")
;; ("breaklines=true")
;; ("escapeinside=||")
;; ("mathescape=true")))
;; (setq org-latex-minted-options '())
;; (setq org-latex-pdf-process
;; (list "latexmk -shell-escape -bibtex -pdfxe -f %f"))
;; (add-hook 'org-mode-hook (lambda () (org-superstar-mode 1)))
;; (add-hook 'org-mode-hook 'auto-fill-mode)
;; (add-hook 'org-mode-hook 'org-indent-mode)
;; Only env in beamer
;; (add-hook 'org-beamer-hook '(add-to-list 'org-beamer-environments-extra
;; '("onlyenv" "O" "\\begin{onlyenv}%a" "\\end{onlyenv}")))
Install elfeed
(use-package elfeed)
Set up list of feeds
(when (load "~/org/feeds.el" t)
(require 'feeds))
(straight-use-package 'prescient)
(straight-use-package 'selectrum-prescient)
(use-package vertico
:straight (:files (:defaults "extensions/*"))
:init
(vertico-mode))
(straight-use-package 'vertico-prescient)
(vertico-prescient-mode +1)
(prescient-persist-mode +1)
;; Nicer movement between layers
(define-key vertico-map (kbd "C-<left>") 'vertico-directory-up)
(define-key vertico-map (kbd "C-<right>") 'vertico-insert)
;; Just so you don't have to keep releasing ctrl.
(define-key vertico-map (kbd "C-<up>") 'vertico-previous)
(define-key vertico-map (kbd "C-<down>") 'vertico-next)
(use-package marginalia
:bind (:map minibuffer-local-map
("M-A" . marginalia-cycle))
:init
(marginalia-mode))
We start by setting up smtpmail
(setq wl-draft-send-mail-function 'wl-draft-send-mail-with-smtp
smtpmail-debug-info t
smtpmail-default-smtp-server "smtp.fastmail.com"
smtpmail-local-domain "erk.dev"
smtpmail-smtp-user "[email protected]"
smtpmail-smtp-server "smtp.fastmail.com"
smtpmail-stream-type 'ssl
smtpmail-smtp-service 465
)
We then setup wanderlust, here it should be noted a large part of the config resides in ~~/.wl~.
(straight-override-recipe
'(semi :host github :repo "wanderlust/semi" :branch "semi-1_14-wl"))
(straight-override-recipe
'(flim :host github :repo "wanderlust/flim" :branch "flim-1_14-wl"))
(straight-override-recipe
'(apel :host github :repo "wanderlust/apel" :branch "apel-wl"))
(straight-override-recipe
'(wanderlust :host github :repo "wanderlust/wanderlust" :branch "master"))
(use-package wanderlust
:ensure t
:no-require t)
;;Wanderlust
(require 'wl)
(autoload 'wl "wl" "Wanderlust" t)
(autoload 'wl-other-frame "wl" "Wanderlust on new frame." t)
(autoload 'wl-draft "wl-draft" "Write draft with Wanderlust." t)
;; Lidt mere af emnelinjen i `summary-mode`
(setq wl-summary-width 120)
(setq wl-summary-line-format "%n%T%P%M/%D(%W)%h:%m %t%[%26(%c %f%) %] %s")
;; Use ~/.authinfo.gpg for password store
(setq elmo-passwd-storage-type 'auth-source)
;; Open ~/.wl in emacs lisp mode.
(add-to-list 'auto-mode-alist '("\.wl$" . emacs-lisp-mode))
For Lobste.rs we use POP3 to not fill the mailserver up.
(setq elmo-maildir-folder-path "~/Mail")
Install lsp mode
(require 'yasnippet)
(use-package go-mode)
(use-package eglot)
(require 'eglot)
(setq eglot-inlay-hints-mode nil) ;; This does not work
(setq eglot-ignored-server-capabilities '(:inlayHintProvider))
(add-to-list 'eglot-server-programs
`(rust-mode . ("rust-analyzer" :initializationOptions
( :procMacro (:enable t)
:cargo ( :buildScripts (:enable t)))))
`(go-mode . ("/home/erk/go/bin/gopls")))
(use-package corfu
:straight (:files (:defaults "extensions/*"))
;; Optional customizations
:custom
;; (corfu-cycle t) ;; Enable cycling for `corfu-next/previous'
(corfu-auto t) ;; Enable auto completion
(corfu-separator ?\s) ;; Orderless field separator
;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary
(corfu-quit-no-match 'separator)
;; (corfu-preview-current nil) ;; Disable current candidate preview
;; (corfu-preselect 'prompt) ;; Preselect the prompt
;; (corfu-on-exact-match nil) ;; Configure handling of exact matches
;; (corfu-scroll-margin 5) ;; Use scroll margin
:init
(global-corfu-mode))
(setq completion-cycle-threshold 3)
;; Emacs 28: 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)
;; Enable indentation+completion using the TAB key.
;; `completion-at-point' is often bound to M-TAB.
(setq tab-always-indent 'complete)
Install packages needed for rustic with rust-analyzer
;;(setq lsp-keymap-prefix (kbd "C-."))
;;(define-key lsp-mode-map (kbd "C-.") lsp-command-map)
;;(use-package company)
(straight-use-package
'(rustic :type git
:host github
:repo "emacs-rustic/rustic"))
(setq rustic-lsp-client 'eglot)
Initialize and configure rustic
;; (set-face-attribute 'rust-ampersand-face nil
;; :inherit nil)
(add-hook 'rustic-mode-hook #'yas-minor-mode)
;; (remove-hook 'rustic-mode-hook 'flycheck-mode)
;; (define-key rustic-mode-map (kbd "TAB") #'company-indent-or-complete-common)
;; (setq company-tooltip-align-annotations t
;; company-idle-delay 1
;; company-show-numbers t)
;; (use-package lean4-mode
;; :straight (lean4-mode
;; :type git
;; :host github
;; :repo "leanprover/lean4-mode"
;; :files ("*.el" "data"))
;; ;; to defer loading the package until required
;; :commands (lean4-mode))
Install Magit and magit forge and setup ssh agent
(use-package magit)
(use-package forge
:after magit)
;; (use-package orgit-forge)
;; (use-package exec-path-from-shell)
;; (exec-path-from-shell-copy-env "SSH_AGENT_PID")
;; (exec-path-from-shell-copy-env "SSH_AUTH_SOCK")
(use-package keychain-environment
:init
(keychain-refresh-environment))
(use-package magit-delta
:after magit)
(setq magit-delta-delta-executable "/usr/bin/delta"
magit-delta-hide-plus-minus-markers nil
magit-delta-default-dark-theme "DarkNeon"
magit-delta-default-light-theme "1337")
(use-package magit-todos
:after magit
:config (magit-todos-mode 1))
(add-hook 'magit-mode-hook (lambda () (magit-delta-mode +1)))
;; Example configuration for Consult
(use-package consult
;; Replace bindings. Lazily loaded due by `use-package'.
:bind (;; C-c bindings in `mode-specific-map'
("M-g g" . consult-goto-line) ;; orig. goto-line
("M-g M-g" . consult-goto-line) ;; orig. goto-line
("M-s d" . consult-find)
("M-s D" . consult-locate)
("M-s r" . consult-ripgrep)
;; 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
("C-." . consult-line) ;; needed by consult-line to detect isearch
("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
;; The :init configuration is always executed (Not lazy)
:init
;; Configure other variables and modes in the :config section,
;; after lazily loading the package.
:config
(setq consult-preview-key 'any)
(consult-customize
consult-theme :preview-key '(:debounce 0.2 any)
consult-ripgrep consult-git-grep consult-grep
consult-bookmark consult-recent-file consult-xref
consult--source-bookmark consult--source-file-register
consult--source-recent-file consult--source-project-recent-file
;; :preview-key "M-."
:preview-key '(:debounce 0.4 any))
;; Optionally configure the narrowing key.
;; Both < and C-+ work reasonably well.
(setq consult-narrow-key "<")) ;; "C-+"
(use-package consult-yasnippet)
(require 'consult-yasnippet)
(use-package orderless
:ensure t
:init
(setq completion-styles '(orderless basic)
completion-category-defaults nil
completion-category-overrides '((file (styles basic partial-completion)))))
(use-package affe
:config
;; Manual preview key for `affe-grep'
(consult-customize affe-grep :preview-key "m-o"))
(defun affe-orderless-regexp-compiler (input _type _ignorecase)
(setq input (orderless-pattern-componsiler input))
(cons input (apply-partially #'orderless--highlight input t)))
(setq affe-regexp-compiler #'affe-orderless-regexp-compiler)
(add-to-list 'auto-mode-alist '(".*\.emms$" . emacs-lisp-mode))
(use-package emms)
(require 'emms-setup)
(emms-all)
(setq emms-player-list '(emms-player-mpv)
emms-info-functions '(emms-info-native))
(require 'emms-streams)
(customize-set-variable 'emms-player-mpv-update-metadata t)
(use-package transient)
(require 'rust-transient)
(if (string= (system-name) "fedora")
(require 'work))
(use-package pdf-tools
:ensure t
:init
(pdf-tools-install))
(use-package futhark-mode)
(straight-use-package
'(eat :type git
:host codeberg
:repo "akib/emacs-eat"
:files ("*.el" ("term" "term/*.el") "*.texi"
"*.ti" ("terminfo/e" "terminfo/e/*")
("terminfo/65" "terminfo/65/*")
("integration" "integration/*")
(:exclude ".dir-locals.el" "*-tests.el"))))
(straight-use-package 'tree-sitter)
(straight-use-package 'tree-sitter-langs)
(require 'tree-sitter)
(require 'tree-sitter-langs)
(global-tree-sitter-mode)
(add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode)
(straight-use-package 'scratch)
(global-set-key (kbd "C-c s") #'scratch)
(straight-use-package 'rg)
(global-set-key (kbd "C-c r") #'rg)
(global-set-key (kbd "C-c t") #'rg-menu)
;; Turn off the most annoying keybinds
(global-unset-key (kbd "<insert>"))
(global-unset-key (kbd "C-z"))
;; Windmove alt+←↓↑→
(windmove-default-keybindings 'meta)
;; (global-set-key (kbd "C-s") 'swiper)
;; (global-set-key (kbd "C-x b") 'ivy-switch-buffer)
;; (global-set-key (kbd "C-c C-r") 'ivy-resume)
;; (global-set-key (kbd "M-x") 'counsel-M-x)
;; (global-set-key (kbd "C-x C-f") 'counsel-find-file)
(global-set-key (kbd "<f9>") 'display-line-numbers-mode)
(global-set-key (kbd "<f12>") 'menu-bar-mode)
;; Org mode
;; (global-set-key (kbd "C-c l") 'org-store-link)
;; (global-set-key (kbd "C-c a") 'org-agenda)
;; Multiple cursors
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
(global-set-key (kbd "C->") 'mc/mark-next-like-this)
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
;; Eglot
(define-key eglot-mode-map (kbd "C-. a") 'eglot-code-actions)
(define-key eglot-mode-map (kbd "C-. =") 'eglot-format-buffer)
(define-key eglot-mode-map (kbd "C-. r") 'eglot-rename)
(define-key eglot-mode-map (kbd "C-. h") 'eldoc-doc-buffer)
(define-key eglot-mode-map (kbd "C-. q") 'eglot-shutdown)
(define-key eglot-mode-map (kbd "C-. g") 'xref-find-references)
(define-key eglot-mode-map (kbd "C-. i") 'eglot-find-implementation)
(define-key eglot-mode-map (kbd "C-. n") 'flymake-goto-next-error)
(define-key eglot-mode-map (kbd "C-. p") 'flymake-goto-prev-error)