105 lines
3.0 KiB
EmacsLisp
105 lines
3.0 KiB
EmacsLisp
;;; lsp-rust.el --- Rust support for lsp-mode
|
|
|
|
;; Copyright (C) 2017 Vibhav Pant <vibhavp@gmail.com>
|
|
|
|
;; Author: Vibhav Pant <vibhavp@gmail.com>
|
|
;; Version: 1.0
|
|
;; Package-Requires: ((lsp-mode "3.0"))
|
|
;; Keywords: rust
|
|
;; URL: https://github.com/emacs-lsp/lsp-rust
|
|
|
|
;;; Commentary:
|
|
|
|
;; lsp-mode client for the Rust Language Server (RLS).
|
|
;; See https://github.com/rust-lang-nursery/rls
|
|
;;
|
|
;; # Setup
|
|
;;
|
|
;; You can load lsp-rust after lsp-mode by adding the following to your init
|
|
;; file:
|
|
;;
|
|
;; (with-eval-after-load 'lsp-mode
|
|
;; (require 'lsp-rust)
|
|
;; (add-hook 'rust-mode-hook #'lsp-rust-enable))
|
|
;;
|
|
;; You may want to customize the command that lsp-rust uses to launch the RLS.
|
|
;; See `lsp-rust-rust-command'.
|
|
|
|
;;; Code:
|
|
|
|
(require 'lsp-mode)
|
|
(require 'cl-lib)
|
|
(require 'json)
|
|
|
|
(defvar lsp-rust--config-options (make-hash-table))
|
|
(defvar lsp-rust--diag-counters (make-hash-table))
|
|
|
|
(defun lsp-rust--rls-command ()
|
|
(let ((rls-root (getenv "RLS_ROOT"))
|
|
(rls-path (executable-find "rls")))
|
|
(if rls-path
|
|
rls-path
|
|
(when rls-root
|
|
`("cargo" "+nightly" "run" "--quiet"
|
|
,(concat "--manifest-path="
|
|
(concat
|
|
(file-name-as-directory (expand-file-name rls-root))
|
|
"Cargo.toml"))
|
|
"--release")))))
|
|
|
|
(defun lsp-rust--get-root ()
|
|
(let (dir)
|
|
(unless
|
|
(ignore-errors
|
|
(let* ((output (shell-command-to-string "cargo locate-project"))
|
|
(js (json-read-from-string output)))
|
|
(setq dir (cdr (assq 'root js)))))
|
|
(error "Couldn't find root for project at %s" default-directory))
|
|
(file-name-directory dir)))
|
|
|
|
(defconst lsp-rust--handlers
|
|
'(("rustDocument/diagnosticsBegin" . (lambda (_w _p)))
|
|
("rustDocument/diagnosticsEnd" .
|
|
(lambda (w _p)
|
|
(when (< (cl-decf (gethash w lsp-rust--diag-counters 0)) 0)
|
|
(message "RLS: done"))))
|
|
("rustDocument/beginBuild" .
|
|
(lambda (w _p)
|
|
(cl-incf (gethash w lsp-rust--diag-counters 0))
|
|
(message "RLS: working")))))
|
|
|
|
(defun lsp-rust--initialize-client (client)
|
|
(mapcar #'(lambda (p) (lsp-client-on-notification client (car p) (cdr p)))
|
|
lsp-rust--handlers))
|
|
|
|
(lsp-define-stdio-client lsp-rust "rust" #'lsp-rust--get-root nil
|
|
:command-fn #'lsp-rust--rls-command
|
|
:initialize #'lsp-rust--initialize-client)
|
|
|
|
(defun lsp-rust--set-configuration ()
|
|
(lsp--set-configuration `(:rust ,lsp-rust--config-options)))
|
|
|
|
(add-hook 'lsp-after-initialize-hook 'lsp-rust--set-configuration)
|
|
|
|
(defun lsp-rust-set-config (name option)
|
|
"Set a config option in the rust lsp server."
|
|
(puthash name option lsp-rust--config-options))
|
|
|
|
(defun lsp-rust-set-build-lib (build)
|
|
"Enable(t)/Disable(nil) building the lib target."
|
|
(lsp-rust-set-config "build_lib" build))
|
|
|
|
(defun lsp-rust-set-build-bin (build)
|
|
"The bin target to build."
|
|
(lsp-rust-set-config "build_bin" build))
|
|
|
|
(defun lsp-rust-set-cfg-test (val)
|
|
"Enable(t)/Disable(nil) #[cfg(test)]."
|
|
(lsp-rust-set-config "cfg_test" val))
|
|
|
|
(defun lsp-rust-set-goto-def-racer-fallback (val)
|
|
"Enable(t)/Disable(nil) goto-definition should use racer as fallback."
|
|
(lsp-rust-set-config "goto_def_racer_fallback" val))
|
|
|
|
(provide 'lsp-rust)
|