about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/etc/emacs/rust-mode-tests.el64
-rw-r--r--src/etc/emacs/rust-mode.el100
2 files changed, 127 insertions, 37 deletions
diff --git a/src/etc/emacs/rust-mode-tests.el b/src/etc/emacs/rust-mode-tests.el
index c0543b691a2..bdd7d63a8be 100644
--- a/src/etc/emacs/rust-mode-tests.el
+++ b/src/etc/emacs/rust-mode-tests.el
@@ -452,6 +452,70 @@ fn foo() {
 "
    ))
 
+(ert-deftest indent-indented-match ()
+  (test-indent
+   "
+fn foo() {
+    let x = 
+        match blah {
+            Pattern |
+            Pattern2 => {
+                hello()
+            },
+            _ => whatever
+        };
+    y();
+}
+"
+   ))
+
+(ert-deftest indent-curly-braces-within-parens ()
+  (test-indent
+   "
+fn foo() {
+    let x = 
+        foo(bar(|x| {
+            only_one_indent_here();
+        }));
+    y();
+}
+"
+   ))
+
+(ert-deftest indent-weirdly-indented-block ()
+  (rust-test-manip-code
+   "
+fn foo() {
+ {
+this_block_is_over_to_the_left_for_some_reason();
+ }
+
+}
+"
+   16
+   #'indent-for-tab-command
+   "
+fn foo() {
+ {
+     this_block_is_over_to_the_left_for_some_reason();
+ }
+
+}
+"
+   ))
+
+(ert-deftest indent-multi-line-attrib ()
+  (test-indent
+   "
+#[attrib(
+    this,
+    that,
+    theotherthing)]
+mod function_with_multiline_attribute() {}
+"
+   ))
+
+
 ;; Make sure that in effort to cover match patterns we don't mistreat || or expressions
 (ert-deftest indent-nonmatch-or-expression ()
   (test-indent
diff --git a/src/etc/emacs/rust-mode.el b/src/etc/emacs/rust-mode.el
index a2e1fc0b99f..b304df8f14c 100644
--- a/src/etc/emacs/rust-mode.el
+++ b/src/etc/emacs/rust-mode.el
@@ -59,61 +59,87 @@
 	(backward-word 1))
       (current-column))))
 
+(defun rust-rewind-to-beginning-of-current-level-expr ()
+  (let ((current-level (rust-paren-level)))
+    (back-to-indentation)
+    (while (> (rust-paren-level) current-level)
+      (backward-up-list)
+      (back-to-indentation))))
+
 (defun rust-mode-indent-line ()
   (interactive)
   (let ((indent
          (save-excursion
            (back-to-indentation)
-           (let ((level (rust-paren-level)))
+           ;; Point is now at beginning of current line
+           (let* ((level (rust-paren-level))
+                  (baseline
+                   ;; Our "baseline" is one level out from the indentation of the expression
+                   ;; containing the innermost enclosing opening bracket.  That
+                   ;; way if we are within a block that has a different
+                   ;; indentation than this mode would give it, we still indent
+                   ;; the inside of it correctly relative to the outside.
+                   (if (= 0 level)
+                       0
+                     (save-excursion
+                       (backward-up-list)
+                       (rust-rewind-to-beginning-of-current-level-expr)
+                       (+ (current-column) rust-indent-offset)))))
              (cond
               ;; A function return type is indented to the corresponding function arguments
               ((looking-at "->")
                (save-excursion
                  (backward-list)
                  (or (rust-align-to-expr-after-brace)
-                     (* rust-indent-offset (+ 1 level)))))
+                     (+ baseline rust-indent-offset))))
 
               ;; A closing brace is 1 level unindended
-              ((looking-at "}") (* rust-indent-offset (- level 1)))
+              ((looking-at "}") (- baseline rust-indent-offset))
 
               ;; Doc comments in /** style with leading * indent to line up the *s
               ((and (nth 4 (syntax-ppss)) (looking-at "*"))
-               (+ 1 (* rust-indent-offset level)))
+               (+ 1 baseline))
 
               ;; If we're in any other token-tree / sexp, then:
-              ;;  - [ or ( means line up with the opening token
-              ;;  - { means indent to either nesting-level * rust-indent-offset,
-              ;;    or one further indent from that if either current line
-              ;;    begins with 'else', or previous line didn't end in
-              ;;    semi, comma, brace or single pipe (other than whitespace and line
-              ;;    comments) , and wasn't an attribute.  But if we have
-              ;;    something after the open brace and ending with a comma,
-              ;;    treat it as fields and align them.  PHEW.
-              ((> level 0)
-               (let ((pt (point)))
-                 (rust-rewind-irrelevant)
-                 (backward-up-list)
-                 (or (and (looking-at "[[({]")
-                          (rust-align-to-expr-after-brace))
-                     (progn
-                       (goto-char pt)
-                       (back-to-indentation)
-                       (if (looking-at "\\<else\\>")
-                           (* rust-indent-offset (+ 1 level))
-                         (progn
-                           (goto-char pt)
-                           (beginning-of-line)
-                           (rust-rewind-irrelevant)
-                           (end-of-line)
-                           (if (looking-back "\\(?:[(,:;?[{}]\\|[^|]|\\)[[:space:]]*\\(?://.*\\)?")
-                               (* rust-indent-offset level)
-                             (back-to-indentation)
-                             (if (looking-at "#")
-                                 (* rust-indent-offset level)
-                               (* rust-indent-offset (+ 1 level))))))))))
-
-              ;; Otherwise we're in a column-zero definition
-              (t 0))))))
+              (t
+               (or
+                ;; If we are inside a pair of braces, with something after the
+                ;; open brace on the same line and ending with a comma, treat
+                ;; it as fields and align them.
+                (when (> level 0)
+                  (save-excursion
+                    (rust-rewind-irrelevant)
+                    (backward-up-list)
+                    ;; Point is now at the beginning of the containing set of braces
+                    (rust-align-to-expr-after-brace)))
+
+                (progn
+                  (back-to-indentation)
+                  ;; Point is now at the beginning of the current line
+                  (if (or
+                       ;; If this line begins with "else" or "{", stay on the
+                       ;; baseline as well (we are continuing an expression,
+                       ;; but the "else" or "{" should align with the beginning
+                       ;; of the expression it's in.)
+                       (looking-at "\\<else\\>\\|{")
+                       
+                       (save-excursion
+                         (rust-rewind-irrelevant)
+                         ;; Point is now at the end of the previous ine
+                         (or
+                          ;; If we are at the first line, no indentation is needed, so stay at baseline...
+                          (= 1 (line-number-at-pos (point)))
+                          ;; ..or if the previous line ends with any of these:
+                          ;;     { ? : ( , ; [ }
+                          ;; then we are at the beginning of an expression, so stay on the baseline...
+                          (looking-back "[(,:;?[{}]\\|[^|]|")
+                          ;; or if the previous line is the end of an attribute, stay at the baseline...
+                          (progn (rust-rewind-to-beginning-of-current-level-expr) (looking-at "#")))))
+                      baseline
+
+                    ;; Otherwise, we are continuing the same expression from the previous line,
+                    ;; so add one additional indent level
+                    (+ baseline rust-indent-offset))))))))))
     (when (not (eq (current-indentation) indent))
       ;; If we're at the beginning of the line (before or at the current
       ;; indentation), jump with the indentation change.  Otherwise, save the