Files
emacs-dotfiles/.config.d/15-lsp.el

228 lines
7.6 KiB
EmacsLisp

;;; 15-lsp.el --- Setup LSP -*- no-byte-compile: t; lexical-binding: t; -*-
;;; Commentary:
;; Despite the name, this file not only sets up LSP integration, but
;; also native Emacs modes for various programming lanuguages, such as
;; Prolog, that do not use LSP.
;;; Code:
;; This package provides syntax highlighting and some utilities for
;; working with rust code.
(use-package rust-mode
:ensure t
:defer t
:commands (rust-mode))
(add-hook 'rust-mode-hook #'eglot-ensure)
;; Clippy backend for flymake so we get propa error reporting in Rust
(use-package flymake-clippy
:hook (rust-mode . flymake-clippy-setup-backend))
(defun manually-activate-flymake ()
(add-hook 'flymake-diagnostic-functions #'eglot-flymake-backend nil t)
(flymake-mode 1))
;; Eglot is the built-in LSP client.
(use-package eglot
:ensure nil
:defer t
:commands (eglot
eglot-rename
eglot-ensure
eglot-rename
eglot-format-buffer)
:hook ((eglot-managed-mode . manually-activate-flymake))
:custom
(eglot-report-progress nil) ; Prevent minibuffer spam
:config
(add-to-list 'eglot-server-programs '((rust-mode) . ("rust-analyzer" :initializationOptions
( :procMacro (:enable t)
:cargo ( :buildScripts (:enable t) )))))
(add-to-list 'eglot-server-programs '(nix-mode . ("nil")))
(add-to-list 'eglot-stay-out-of 'flymake)
;; Optimizations
(fset #'jsonrpc--log-event #'ignore)
(setq jsonrpc-event-hook nil)
)
;; This function raises the window to the front using KDE KWin.
(defun my-raise-window ()
"Raises the window to the front using KDE KWin.
Won't work if the script is not there."
(call-process-shell-command "~/wayland-window -f emacs &" nil 0))
;; Usually, when I open a file with emacsclient and the frame already exists, I
;; want it to be raised to the top. Unfortunately, that does not happen by
;; default. Here is my solution.
(add-hook 'server-visit-hook #'my-raise-window)
;; This package provides syntax highlighting for gdscript.
(use-package gdscript-mode
:ensure t
:defer t
:commands (gdscript-mode))
(add-hook 'gdscript-mode-hook #'eglot-ensure)
;; This package provides integration with Prolog (SWI).
(use-package sweeprolog
:straight (sweeprolog :type git
:host nil
:repo "https://git.sr.ht/~eshel/sweep"
:branch "main"
:files ("*.el" "sweep.pl" "sweep.texi")) ; Custom recipe because
; the normal one did not
; build properly.
:ensure t
:defer t
:commands (sweeprolog-mode
sweeprolog-top-level)
:init
(setq sweeprolog-swipl-path "swipl"))
;; This package provides integration with Prolog (scryer) Note that editing
;; prolog is supported through built-in prolog-mode, this only allows actually
;; consulting prolog from within emacs.
(use-package ediprolog
:ensure t
:defer t
:commands (prolog-mode)
:config
(my-ediprolog-select-system "swi-prolog"))
(defun ediprolog-set-term-type (orig &rest args)
"Advice to set the TERM env var to dumb for the function call.
Originally created for scryer prolog, as either it itself or systemd-run
used to constrain its resources assumed that the terminal supports
escape codes (it does not in this case), so this was used as an
\":around\" advice on 'ediprolog-run-prolog', to clearly indicate that
control codes are not supported."
(let ((process-environment process-environment))
(setenv "TERM" "dumb")
(apply orig args)))
(with-eval-after-load "prolog"
(bind-key "C-c C-e" #'ediprolog-dwim prolog-mode-map)
(advice-add 'ediprolog-run-prolog :around #'ediprolog-set-term-type))
(add-to-list 'auto-mode-alist '("\\.plt?\\'" . prolog-mode))
(add-to-list 'auto-mode-alist '("\\.axaml?\\'" . nxml-mode))
;; Nix language
(use-package nix-mode
:ensure t
:defer t
:commands (nix-mode)
:hook
(nix-mode . eglot-ensure))
;; Common Lisp
(use-package sly
:ensure t
:defer t
:commands (sly)
:init
(setq inferior-lisp-program "sbcl"))
;; Racket lisp
(use-package racket-mode
:ensure t
:defer t
:commands (racket-mode racket-xp-mode)
:hook ((racket-mode . racket-xp-mode))
:bind (("C-c C-n" . racket-run-and-switch-to-repl))
:config
(setq racket-xp-eldoc-level 'summary))
(defun racket-restart ()
"Restarts the backend and reinitializes the mode to cope with the
consequences of direnv activating after racket-mode(-s)."
(interactive)
(when (eq major-mode 'racket-mode)
(racket-stop-back-end)
(racket-start-back-end)
(racket-mode)))
;; Markdown
(use-package markdown-mode
:ensure t
:defer t)
(if (memq 'lispy-autoloads features)
(add-hook 'emacs-lisp-mode-hook (lambda () (lispy-mode 1))))
;; This package adds indent bars. Currently only configured for rust and python.
(use-package indent-bars
:ensure t
:defer t
:custom
(indent-bars-no-descend-lists t) ; no extra bars in continued func arg lists
(indent-bars-treesit-support t)
(indent-bars-treesit-ignore-blank-lines-types '("module"))
;; Add other languages as needed
(indent-bars-treesit-scope '((python function_definition class_definition for_statement
if_statement with_statement while_statement)
(rust trait_item impl_item
macro_definition macro_invocation
struct_item enum_item mod_item
const_item let_declaration
function_item for_expression
if_expression loop_expression
while_expression match_expression
match_arm call_expression
token_tree token_tree_pattern
token_repetition)))
(indent-bars-treesit-wrap '((rust arguments parameters)))
:hook ((python-base-mode yaml-mode rust-mode) . indent-bars-mode))
;; Configure Tempel
(use-package tempel
:bind (("C-S-e" . tempel-complete) ;; Alternative tempel-expand
("M-*" . tempel-insert))
:init
;; Setup completion at point
(defun tempel-setup-capf ()
;; Add the Tempel Capf to `completion-at-point-functions'. `tempel-expand'
;; only triggers on exact matches. We add `tempel-expand' *before* the main
;; programming mode Capf, such that it will be tried first.
(setq-local completion-at-point-functions
(cons #'tempel-expand completion-at-point-functions))
;; Alternatively use `tempel-complete' if you want to see all matches. Use
;; a trigger prefix character in order to prevent Tempel from triggering
;; unexpectly.
;; (setq-local corfu-auto-trigger "/"
;; completion-at-point-functions
;; (cons (cape-capf-trigger #'tempel-complete ?/)
;; completion-at-point-functions))
)
(add-hook 'conf-mode-hook 'tempel-setup-capf)
(add-hook 'prog-mode-hook 'tempel-setup-capf)
(add-hook 'text-mode-hook 'tempel-setup-capf)
(setq tempel-path (concat minimal-emacs-user-directory "templates"))
;; Optionally make the Tempel templates available to Abbrev,
;; either locally or globally. `expand-abbrev' is bound to C-x '.
;; (add-hook 'prog-mode-hook #'tempel-abbrev-mode)
;; (global-tempel-abbrev-mode)
)
;; Optional: Add tempel-collection if you want ready-made templates. Yes sir, I
;; do.
(use-package tempel-collection)
;;; 15-lsp.el end here