summaryrefslogtreecommitdiff
path: root/.emacs.d/lisp/rust-cargo.el
diff options
context:
space:
mode:
Diffstat (limited to '.emacs.d/lisp/rust-cargo.el')
-rw-r--r--.emacs.d/lisp/rust-cargo.el124
1 files changed, 124 insertions, 0 deletions
diff --git a/.emacs.d/lisp/rust-cargo.el b/.emacs.d/lisp/rust-cargo.el
new file mode 100644
index 0000000..cfbcd81
--- /dev/null
+++ b/.emacs.d/lisp/rust-cargo.el
@@ -0,0 +1,124 @@
1;;; rust-cargo.el --- Support for cargo -*-lexical-binding: t-*-
2;;; Commentary:
3
4;; This library implements support for running `cargo'.
5
6;;; Code:
7
8(require 'json)
9
10;;; Options
11
12(defcustom rust-cargo-bin "cargo"
13 "Path to cargo executable."
14 :type 'string
15 :group 'rust-mode)
16
17(defcustom rust-always-locate-project-on-open nil
18 "Whether to run `cargo locate-project' every time `rust-mode' is activated."
19 :type 'boolean
20 :group 'rust-mode)
21
22(defcustom rust-cargo-default-arguments ""
23 "Default arguments when running common cargo commands."
24 :type 'string
25 :group 'rust-mode)
26
27;;; Buffer Project
28
29(defvar-local rust-buffer-project nil)
30
31(defun rust-buffer-project ()
32 "Get project root if possible."
33 ;; Copy environment variables into the new buffer, since
34 ;; with-temp-buffer will re-use the variables' defaults, even if
35 ;; they have been changed in this variable using e.g. envrc-mode.
36 ;; See https://github.com/purcell/envrc/issues/12.
37 (let ((env process-environment)
38 (path exec-path))
39 (with-temp-buffer
40 ;; Copy the entire environment just in case there's something we
41 ;; don't know we need.
42 (setq-local process-environment env)
43 ;; Set PATH so we can find cargo.
44 (setq-local exec-path path)
45 (let ((ret (process-file rust-cargo-bin nil (list (current-buffer) nil) nil "locate-project" "--workspace")))
46 (when (/= ret 0)
47 (error "`cargo locate-project' returned %s status: %s" ret (buffer-string)))
48 (goto-char 0)
49 (let ((output (json-read)))
50 (cdr (assoc-string "root" output)))))))
51
52(defun rust-buffer-crate ()
53 "Try to locate Cargo.toml using `locate-dominating-file'."
54 (let ((dir (locate-dominating-file default-directory "Cargo.toml")))
55 (if dir dir default-directory)))
56
57(defun rust-update-buffer-project ()
58 (setq-local rust-buffer-project (rust-buffer-project)))
59
60(defun rust-maybe-initialize-buffer-project ()
61 (setq-local rust-buffer-project nil)
62 (when rust-always-locate-project-on-open
63 (rust-update-buffer-project)))
64
65(add-hook 'rust-mode-hook #'rust-maybe-initialize-buffer-project)
66
67;;; Internal
68
69(defun rust--compile (format-string &rest args)
70 (when (null rust-buffer-project)
71 (rust-update-buffer-project))
72 (let ((default-directory
73 (or (and rust-buffer-project
74 (file-name-directory rust-buffer-project))
75 default-directory)))
76 (compile (apply #'format format-string args))))
77
78;;; Commands
79
80(defun rust-check ()
81 "Compile using `cargo check`"
82 (interactive)
83 (rust--compile "%s check %s" rust-cargo-bin rust-cargo-default-arguments))
84
85(defun rust-compile ()
86 "Compile using `cargo build`"
87 (interactive)
88 (rust--compile "%s build %s" rust-cargo-bin rust-cargo-default-arguments))
89
90(defun rust-compile-release ()
91 "Compile using `cargo build --release`"
92 (interactive)
93 (rust--compile "%s build --release" rust-cargo-bin))
94
95(defun rust-run ()
96 "Run using `cargo run`"
97 (interactive)
98 (rust--compile "%s run %s" rust-cargo-bin rust-cargo-default-arguments))
99
100(defun rust-run-release ()
101 "Run using `cargo run --release`"
102 (interactive)
103 (rust--compile "%s run --release" rust-cargo-bin))
104
105(defun rust-test ()
106 "Test using `cargo test`"
107 (interactive)
108 (rust--compile "%s test %s" rust-cargo-bin rust-cargo-default-arguments))
109
110(defun rust-run-clippy ()
111 "Run `cargo clippy'."
112 (interactive)
113 (when (null rust-buffer-project)
114 (rust-update-buffer-project))
115 (let* ((args (list rust-cargo-bin "clippy"
116 (concat "--manifest-path=" rust-buffer-project)))
117 ;; set `compile-command' temporarily so `compile' doesn't
118 ;; clobber the existing value
119 (compile-command (mapconcat #'shell-quote-argument args " ")))
120 (rust--compile compile-command)))
121
122;;; _
123(provide 'rust-cargo)
124;;; rust-cargo.el ends here