[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/rust-mode 5e34201 061/486: Add defun motions for rust-mode
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/rust-mode 5e34201 061/486: Add defun motions for rust-mode. |
Date: |
Sat, 7 Aug 2021 09:24:48 -0400 (EDT) |
branch: elpa/rust-mode
commit 5e34201c167f5d976b75c66434c0e1e57bd25804
Author: S Pradeep Kumar <gohanpra@gmail.com>
Commit: S Pradeep Kumar <gohanpra@gmail.com>
Add defun motions for rust-mode.
Specifically, we can now use:
+ beginning-of-defun
+ end-of-defun
+ mark-defun
where "defun" means a Rust item.
+ Add tests in rust-mode-tests.el
+ Fix indentation in rust-mode-tests.el
+ Add support for trait to Imenu
---
rust-mode-tests.el | 250 ++++++++++++++++++++++++++++++++++++++++++++++++-----
rust-mode.el | 44 +++++++++-
2 files changed, 269 insertions(+), 25 deletions(-)
diff --git a/rust-mode-tests.el b/rust-mode-tests.el
index 67e779e..524d474 100644
--- a/rust-mode-tests.el
+++ b/rust-mode-tests.el
@@ -52,24 +52,24 @@ Also, the result should be the same regardless of whether
the code is at the beg
(loop
for pad-at-beginning from 0 to 1
do (loop for pad-at-end from 0 to 1
- with padding-beginning = (if (= 0 pad-at-beginning) "" padding)
- with padding-end = (if (= 0 pad-at-end) "" padding)
- with padding-adjust = (* padding-len pad-at-beginning)
- with padding-beginning = (if (= 0 pad-at-beginning) "" padding)
- with padding-end = (if (= 0 pad-at-end) "" padding)
- ;; If we're adding space to the beginning, and our start position
- ;; is at the very beginning, we want to test within the added space.
- ;; Otherwise adjust the start and end for the beginning padding.
- with start-pos = (if (= 1 start-pos) 1 (+ padding-adjust start-pos))
- with end-pos = (+ end-pos padding-adjust)
- do (loop for pos from start-pos to end-pos
- do (rust-test-manip-code
- (concat padding-beginning unfilled padding-end)
- pos
- (lambda ()
- (let ((fill-column rust-test-fill-column))
- (fill-paragraph)))
- (concat padding-beginning expected padding-end)))))))
+ with padding-beginning = (if (= 0 pad-at-beginning) "" padding)
+ with padding-end = (if (= 0 pad-at-end) "" padding)
+ with padding-adjust = (* padding-len pad-at-beginning)
+ with padding-beginning = (if (= 0 pad-at-beginning) "" padding)
+ with padding-end = (if (= 0 pad-at-end) "" padding)
+ ;; If we're adding space to the beginning, and our start position
+ ;; is at the very beginning, we want to test within the added
space.
+ ;; Otherwise adjust the start and end for the beginning padding.
+ with start-pos = (if (= 1 start-pos) 1 (+ padding-adjust
start-pos))
+ with end-pos = (+ end-pos padding-adjust)
+ do (loop for pos from start-pos to end-pos
+ do (rust-test-manip-code
+ (concat padding-beginning unfilled padding-end)
+ pos
+ (lambda ()
+ (let ((fill-column rust-test-fill-column))
+ (fill-paragraph)))
+ (concat padding-beginning expected
padding-end)))))))
(ert-deftest fill-paragraph-top-level-multi-line-style-doc-comment-second-line
()
(test-fill-paragraph
@@ -262,14 +262,14 @@ fn bar() { }" 14 67))
/// "
103
"This is the second really really really really really really long
paragraph"
- "/// This is the first really
+ "/// This is the first really
/// really really really really
/// really really long paragraph
///
/// This is the second really
/// really really really really
/// really long paragraph"
- ))
+ ))
(ert-deftest auto-fill-multi-line-prefixless ()
(test-auto-fill
@@ -295,7 +295,7 @@ very very very long string
(ert-deftest indent-struct-fields-aligned ()
(test-indent
-"
+ "
struct Foo { bar: int,
baz: int }
@@ -305,7 +305,7 @@ struct Blah {x:int,
(ert-deftest indent-doc-comments ()
(test-indent
-"
+ "
/**
* This is a doc comment
*
@@ -411,7 +411,7 @@ fn nexted_fns(a: fn(b:int,
0
}
"
-))
+ ))
(ert-deftest indent-multi-line-expr ()
(test-indent
@@ -423,4 +423,206 @@ fn foo()
b();
}
"
-))
+ ))
+
+(setq rust-test-motion-string
+ "
+fn fn1(arg: int) -> bool {
+ let x = 5;
+ let y = b();
+ true
+}
+
+fn fn2(arg: int) -> bool {
+ let x = 5;
+ let y = b();
+ true
+}
+
+pub fn fn3(arg: int) -> bool {
+ let x = 5;
+ let y = b();
+ true
+}
+
+struct Foo {
+ x: int
+}
+"
+ rust-test-region-string rust-test-motion-string
+ ;; Symbol -> (line column)
+ rust-test-positions-alist '((start-of-fn1 (2 0))
+ (start-of-fn1-middle-of-line (2 15))
+ (middle-of-fn1 (3 7))
+ (end-of-fn1 (6 0))
+ (between-fn1-fn2 (7 0))
+ (start-of-fn2 (8 0))
+ (middle-of-fn2 (10 4))
+ (before-start-of-fn1 (1 0))
+ (after-end-of-fn2 (13 0))
+ (beginning-of-fn3 (14 0))
+ (middle-of-fn3 (16 4))
+ (middle-of-struct (21 10))
+ (before-start-of-struct (19 0))
+ (after-end-of-struct (23 0))))
+
+(defun rust-get-buffer-pos (pos-symbol)
+ "Get buffer position from POS-SYMBOL.
+
+POS-SYMBOL is a symbol found in `rust-test-positions-alist'.
+Convert the line-column information from that list into a buffer position
value."
+ (interactive "P")
+ (pcase-let ((`(,line ,column) (cadr (assoc pos-symbol
rust-test-positions-alist))))
+ (save-excursion
+ (goto-line line)
+ (move-to-column column)
+ (point))))
+
+;;; TODO: Maybe add an ERT explainer function (something that shows the
+;;; surrounding code of the final point, not just the position).
+(defun rust-test-motion (source-code init-pos final-pos manip-func &optional
&rest args)
+ "Test that MANIP-FUNC moves point from INIT-POS to FINAL-POS.
+
+If ARGS are provided, send them to MANIP-FUNC.
+
+INIT-POS, FINAL-POS are position symbols found in `rust-test-positions-alist'."
+ (with-temp-buffer
+ (rust-mode)
+ (insert source-code)
+ (goto-char (rust-get-buffer-pos init-pos))
+ (apply manip-func args)
+ (should (equal (point) (rust-get-buffer-pos final-pos)))))
+
+(defun rust-test-region (source-code init-pos reg-beg reg-end manip-func
&optional &rest args)
+ "Test that MANIP-FUNC marks region from REG-BEG to REG-END.
+
+INIT-POS is the initial position of point.
+If ARGS are provided, send them to MANIP-FUNC.
+All positions are position symbols found in `rust-test-positions-alist'."
+ (with-temp-buffer
+ (rust-mode)
+ (insert source-code)
+ (goto-char (rust-get-buffer-pos init-pos))
+ (apply manip-func args)
+ (should (equal (list (region-beginning) (region-end))
+ (list (rust-get-buffer-pos reg-beg)
+ (rust-get-buffer-pos reg-end))))))
+
+(ert-deftest rust-beginning-of-defun-from-middle-of-fn ()
+ (rust-test-motion
+ rust-test-motion-string
+ 'middle-of-fn1
+ 'start-of-fn1
+ #'beginning-of-defun))
+
+(ert-deftest rust-beginning-of-defun-from-end ()
+ (rust-test-motion
+ rust-test-motion-string
+ 'end-of-fn1
+ 'start-of-fn1
+ #'beginning-of-defun))
+
+(ert-deftest rust-beginning-of-defun-before-open-brace ()
+ (rust-test-motion
+ rust-test-motion-string
+ 'start-of-fn1-middle-of-line
+ 'start-of-fn1
+ #'beginning-of-defun))
+
+(ert-deftest rust-beginning-of-defun-between-fns ()
+ (rust-test-motion
+ rust-test-motion-string
+ 'between-fn1-fn2
+ 'start-of-fn1
+ #'beginning-of-defun))
+
+(ert-deftest rust-beginning-of-defun-with-arg ()
+ (rust-test-motion
+ rust-test-motion-string
+ 'middle-of-fn2
+ 'start-of-fn1
+ #'beginning-of-defun 2))
+
+(ert-deftest rust-beginning-of-defun-with-negative-arg ()
+ (rust-test-motion
+ rust-test-motion-string
+ 'middle-of-fn1
+ 'beginning-of-fn3
+ #'beginning-of-defun -2))
+
+(ert-deftest rust-beginning-of-defun-pub-fn ()
+ (rust-test-motion
+ rust-test-motion-string
+ 'middle-of-fn3
+ 'beginning-of-fn3
+ #'beginning-of-defun))
+
+(ert-deftest rust-end-of-defun-from-middle-of-fn ()
+ (rust-test-motion
+ rust-test-motion-string
+ 'middle-of-fn1
+ 'between-fn1-fn2
+ #'end-of-defun))
+
+(ert-deftest rust-end-of-defun-from-beg ()
+ (rust-test-motion
+ rust-test-motion-string
+ 'start-of-fn1
+ 'between-fn1-fn2
+ #'end-of-defun))
+
+(ert-deftest rust-end-of-defun-before-open-brace ()
+ (rust-test-motion
+ rust-test-motion-string
+ 'start-of-fn1-middle-of-line
+ 'between-fn1-fn2
+ #'end-of-defun))
+
+(ert-deftest rust-end-of-defun-between-fns ()
+ (rust-test-motion
+ rust-test-motion-string
+ 'between-fn1-fn2
+ 'after-end-of-fn2
+ #'end-of-defun))
+
+(ert-deftest rust-end-of-defun-with-arg ()
+ (rust-test-motion
+ rust-test-motion-string
+ 'middle-of-fn1
+ 'after-end-of-fn2
+ #'end-of-defun 2))
+
+(ert-deftest rust-end-of-defun-with-negative-arg ()
+ (rust-test-motion
+ rust-test-motion-string
+ 'middle-of-fn3
+ 'between-fn1-fn2
+ #'end-of-defun -2))
+
+(ert-deftest rust-mark-defun-from-middle-of-fn ()
+ (rust-test-region
+ rust-test-region-string
+ 'middle-of-fn2
+ 'between-fn1-fn2 'after-end-of-fn2
+ #'mark-defun))
+
+(ert-deftest rust-mark-defun-from-end ()
+ (rust-test-region
+ rust-test-region-string
+ 'end-of-fn1
+ 'before-start-of-fn1 'between-fn1-fn2
+ #'mark-defun))
+
+(ert-deftest rust-mark-defun-start-of-defun ()
+ (rust-test-region
+ rust-test-region-string
+ 'start-of-fn2
+ 'between-fn1-fn2 'after-end-of-fn2
+ #'mark-defun))
+
+(ert-deftest rust-mark-defun-from-middle-of-struct ()
+ (rust-test-region
+ rust-test-region-string
+ 'middle-of-struct
+ 'before-start-of-struct 'after-end-of-struct
+ #'mark-defun))
diff --git a/rust-mode.el b/rust-mode.el
index 2a5f2d9..66cc3c3 100644
--- a/rust-mode.el
+++ b/rust-mode.el
@@ -324,7 +324,7 @@
;;; Imenu support
(defvar rust-imenu-generic-expression
(append (loop for item in
- '("enum" "struct" "type" "mod" "fn")
+ '("enum" "struct" "type" "mod" "fn" "trait")
collect `(nil ,(rust-re-item-def item) 1))
`(("Impl" ,(rust-re-item-def "impl") 1)))
"Value for `imenu-generic-expression' in Rust mode.
@@ -335,6 +335,46 @@ Imenu will show all the enums, structs, etc. at the same
level.
Implementations will be shown under the `Impl` subheading.
Use idomenu (imenu with ido-mode) for best mileage.")
+;;; Defun Motions
+
+;;; Start of a Rust item
+(setq rust-top-item-beg-re
+ (concat "^\\s-*\\(?:priv\\|pub\\)?\\s-*"
+ (regexp-opt
+ '("enum" "struct" "type" "mod" "use" "fn" "static" "impl"
+ "extern" "impl" "static" "trait"
+ ))))
+
+(defun rust-beginning-of-defun (&optional arg)
+ "Move backward to the beginning of the current defun.
+
+With ARG, move backward multiple defuns. Negative ARG means
+move forward.
+
+This is written mainly to be used as `beginning-of-defun-function' for Rust.
+Don't move to the beginning of the line. `beginning-of-defun',
+which calls this, does that afterwards."
+ (interactive "p")
+ (re-search-backward (concat "^\\(" rust-top-item-beg-re "\\)\\b")
+ nil 'move (or arg 1)))
+
+(defun rust-end-of-defun ()
+ "Move forward to the next end of defun.
+
+With argument, do it that many times.
+Negative argument -N means move back to Nth preceding end of defun.
+
+Assume that this is called after beginning-of-defun. So point is
+at the beginning of the defun body.
+
+This is written mainly to be used as `end-of-defun-function' for Rust."
+ (interactive "p")
+ ;; Find the opening brace
+ (re-search-forward "[{]" nil t)
+ (goto-char (match-beginning 0))
+ ;; Go to the closing brace
+ (forward-sexp))
+
;; For compatibility with Emacs < 24, derive conditionally
(defalias 'rust-parent-mode
(if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode))
@@ -374,6 +414,8 @@ Use idomenu (imenu with ido-mode) for best mileage.")
(set (make-local-variable 'comment-multi-line) t)
(set (make-local-variable 'comment-line-break-function)
'rust-comment-indent-new-line)
(set (make-local-variable 'imenu-generic-expression)
rust-imenu-generic-expression)
+ (set (make-local-variable 'beginning-of-defun-function)
'rust-beginning-of-defun)
+ (set (make-local-variable 'end-of-defun-function) 'rust-end-of-defun)
)
- [nongnu] elpa/rust-mode 942d465 398/486: Update Debian installation instructions, (continued)
- [nongnu] elpa/rust-mode 942d465 398/486: Update Debian installation instructions, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode af84c0f 403/486: Merge pull request #319 from phillord/feature/update-emacs-versions, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 4c8754b 430/486: Merge pull request #343 from haroldcarr/master, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 4381a89 433/486: Fix scrolling after rustfmt. (#351), ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 2a8ca9e 443/486: rust-format-show-buffer: default to true., ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 15d31a9 013/486: removed a comma from the keyword list to get, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode e39142b 033/486: Allow customization of indent offset, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 8dc92b2 073/486: Update emacs mode to support new `#![inner(attribute)]` syntax., ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 0800660 068/486: Emacs: stay at the correct position when indenting, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode bc78d17 075/486: rust-mode cleanup., ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 5e34201 061/486: Add defun motions for rust-mode.,
ELPA Syncer <=
- [nongnu] elpa/rust-mode 0e58eb3 076/486: emacs: Add 'box' to keywords, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 226102c 086/486: emacs: Add shebang to test script, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 186583d 096/486: Mark _ as a word constituent to avoid highlighting parts of identifiers as keywords, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 04e4b49 103/486: Add .travis.yml, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode ec81a95 114/486: Merge pull request #22 from nikomatsakis/align-method-chain, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 351cc91 112/486: Merge pull request #16 from MicahChalmer/add-travis, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode b3f87b9 122/486: Make the test driver script a little more informative., ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 19bc0e9 121/486: Merge pull request #30 from MicahChalmer/emacs23-fixup, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode bddc933 124/486: Fix typo in comment, ELPA Syncer, 2021/08/07
- [nongnu] elpa/rust-mode 97f6445 132/486: Merge pull request #38 from MicahChalmer/fix-issue-36, ELPA Syncer, 2021/08/07