diff options
Diffstat (limited to 'editors')
-rw-r--r-- | editors/emacs/ra.el | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/editors/emacs/ra.el b/editors/emacs/ra.el new file mode 100644 index 000000000..099f611be --- /dev/null +++ b/editors/emacs/ra.el | |||
@@ -0,0 +1,87 @@ | |||
1 | ;;; ra.el --- Rust analyzer emacs bindings -*- lexical-binding: t; -*- | ||
2 | ;;; Commentary: | ||
3 | ;;; Small utilities for interacting with Rust analyzer. | ||
4 | ;;; Run | ||
5 | ;;; cargo install --git https://github.com/matklad/rust-analyzer/ ra_cli | ||
6 | ;;; to install the analyzer binary. Then copy-paste the bellow code to | ||
7 | ;;; your `.init.el` and use `ra-extend-selection` and | ||
8 | ;;; `ra-shrink-selection` functions. | ||
9 | ;;; Code: | ||
10 | |||
11 | |||
12 | (defvar ra--selections-cache '(0 0 ())) | ||
13 | (defun ra--cache-tick () | ||
14 | "Get buffer modification count for cache." | ||
15 | (nth 0 ra--selections-cache)) | ||
16 | (defun ra--cache-sel () | ||
17 | "Get current selection for cache." | ||
18 | (nth 1 ra--selections-cache)) | ||
19 | (defun ra--cache-nth-sel (n) | ||
20 | "Get Nth selection." | ||
21 | (nth n (nth 2 ra--selections-cache))) | ||
22 | (defun ra--cache-set-nth-sel (n) | ||
23 | "Get Nth selection." | ||
24 | (setf (nth 1 ra--selections-cache) n) | ||
25 | (nth n (nth 2 ra--selections-cache))) | ||
26 | |||
27 | |||
28 | (defun ra-extend-selection () | ||
29 | "Extend START END region to contain the encompassing syntactic construct." | ||
30 | (interactive) | ||
31 | (let* ((p (point)) | ||
32 | (m (or (and mark-active (mark)) p)) | ||
33 | (start (min p m)) | ||
34 | (end (max p m))) | ||
35 | (ra--extend-selection start end))) | ||
36 | |||
37 | |||
38 | (defun ra-shrink-selection (start end) | ||
39 | "Shrink START END region to contain previous selection." | ||
40 | (interactive "r") | ||
41 | (ra--freshen-cache start end) | ||
42 | (let ((sel-id (ra--cache-sel))) | ||
43 | (if (not (= 0 sel-id)) | ||
44 | (let* ((r (ra--cache-set-nth-sel (- sel-id 1)))) | ||
45 | (push-mark (nth 0 r) t t) | ||
46 | (goto-char (nth 1 r)) | ||
47 | (setq deactivate-mark nil))))) | ||
48 | |||
49 | ; Add this to setup keybinding | ||
50 | ; (require 'rust-mode) | ||
51 | ; (define-key rust-mode-map (kbd "C-w") 'ra-extend-selection) | ||
52 | ; (define-key rust-mode-map (kbd "C-S-w") 'ra-shrink-selection) | ||
53 | |||
54 | |||
55 | |||
56 | (defun ra--extend-selection (start end) | ||
57 | "Extend START END region to contain the encompassing syntactic construct." | ||
58 | (ra--freshen-cache start end) | ||
59 | (let* ((next-sel-idx (+ 1 (ra--cache-sel))) | ||
60 | (r (ra--cache-set-nth-sel next-sel-idx))) | ||
61 | (push-mark (nth 0 r) t t) | ||
62 | (goto-char (nth 1 r)) | ||
63 | (setq deactivate-mark nil))) | ||
64 | |||
65 | (defun ra--selections (start end) | ||
66 | "Get list of selections for START END from Rust analyzer." | ||
67 | (read (with-output-to-string | ||
68 | (call-process-region | ||
69 | (point-min) (point-max) | ||
70 | "ra_cli" nil standard-output nil | ||
71 | "extend-selection" | ||
72 | (number-to-string start) | ||
73 | (number-to-string end))))) | ||
74 | |||
75 | (defun ra--freshen-cache (start end) | ||
76 | "Make selection cache up-to-date for current buffer state and START END." | ||
77 | (if (not (and | ||
78 | (= (buffer-modified-tick) (ra--cache-tick)) | ||
79 | (equal `(,start ,end) (ra--cache-nth-sel (ra--cache-sel))))) | ||
80 | (ra--set-cache start end))) | ||
81 | |||
82 | (defun ra--set-cache (start end) | ||
83 | "Set selections cache for current buffer state and START END." | ||
84 | (setq ra--selections-cache `(,(buffer-modified-tick) 0 ,(ra--selections start end)))) | ||
85 | |||
86 | (provide 'ra) | ||
87 | ;;; ra.el ends here | ||