;;; 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")) ;; Markdown (use-package markdown-mode :ensure t :defer t) ;; Lispy provides structural editing to lisp modes. (use-package lispy :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)) ;; Ellama allows using LLMs from emacs. (use-package ellama :ensure nil :defer t :bind ("C-c e" . ellama) :init (setopt ellama-auto-scroll t) :commands (ellama) :config ;; show ellama context in header line in all buffers (ellama-context-header-line-global-mode +1) ;; show ellama session id in header line in all buffers (ellama-session-header-line-global-mode +1)) ;;; 15-lsp.el end here