about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-02-26 20:01:42 -0800
committerbors <bors@rust-lang.org>2014-02-26 20:01:42 -0800
commit780adfffc39bcb9d32685bd36e2f6b6e6a178dee (patch)
treeecb87056ae5ea12b9fcc0ca925b188a4ee72b13c /src
parentfd02f908befa8f3bd57ef9100970ff783830db5f (diff)
parent04dc3e4985b635d21d2af9b1fd65ad0eb0884b74 (diff)
downloadrust-780adfffc39bcb9d32685bd36e2f6b6e6a178dee.tar.gz
rust-780adfffc39bcb9d32685bd36e2f6b6e6a178dee.zip
auto merge of #12486 : MicahChalmer/rust/emacs-fixes-round-3, r=brson
I've added details in the description of each comment as to what it does, which I won't redundantly repeat here in the PR.  They all relate to indentation in the emacs rust-mode.

What I will note here is that this closes #8787.  It addresses the last remaining case (not in the original issue description but in a comment), of indenting `match` statements.  With the changes here, I believe every problem described in the issue description or comments of #8787 is addressed.

Diffstat (limited to 'src')
-rw-r--r--src/etc/emacs/rust-mode-tests.el169
-rw-r--r--src/etc/emacs/rust-mode.el117
2 files changed, 239 insertions, 47 deletions
diff --git a/src/etc/emacs/rust-mode-tests.el b/src/etc/emacs/rust-mode-tests.el
index 524d474d835..63c1a077c8c 100644
--- a/src/etc/emacs/rust-mode-tests.el
+++ b/src/etc/emacs/rust-mode-tests.el
@@ -425,6 +425,108 @@ fn foo()
 "
    ))
 
+(ert-deftest indent-match ()
+  (test-indent
+   "
+fn foo() {
+    match blah {
+        Pattern => stuff(),
+        _ => whatever
+    }
+}
+"
+   ))
+
+(ert-deftest indent-match-multiline-pattern ()
+  (test-indent
+   "
+fn foo() {
+    match blah {
+        Pattern |
+        Pattern2 => {
+            hello()
+        },
+        _ => whatever
+    }
+}
+"
+   ))
+
+(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)]
+fn 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
+   "
+fn foo() {
+    let x = foo() ||
+        bar();
+}
+"
+   ))
+
 (setq rust-test-motion-string
       "
 fn fn1(arg: int) -> bool {
@@ -450,6 +552,26 @@ struct Foo {
 }
 "
       rust-test-region-string rust-test-motion-string
+      rust-test-indent-motion-string
+      "
+fn blank_line(arg:int) -> bool {
+
+}
+
+fn indenting_closing_brace() {
+    if(true) {
+}
+}
+
+fn indenting_middle_of_line() {
+    if(true) {
+ push_me_out();
+} else {
+               pull_me_back_in();
+}
+}
+"
+
       ;; Symbol -> (line column)
       rust-test-positions-alist '((start-of-fn1 (2 0))
                                   (start-of-fn1-middle-of-line (2 15))
@@ -464,7 +586,17 @@ struct Foo {
                                   (middle-of-fn3 (16 4))
                                   (middle-of-struct (21 10))
                                   (before-start-of-struct (19 0))
-                                  (after-end-of-struct (23 0))))
+                                  (after-end-of-struct (23 0))
+                                  (blank-line-indent-start (3 0))
+                                  (blank-line-indent-target (3 4))
+                                  (closing-brace-indent-start (8 1))
+                                  (closing-brace-indent-target (8 5))
+                                  (middle-push-indent-start (13 2))
+                                  (middle-push-indent-target (13 9))
+                                  (after-whitespace-indent-start (13 1))
+                                  (after-whitespace-indent-target (13 8))
+                                  (middle-pull-indent-start (15 19))
+                                  (middle-pull-indent-target (15 12))))
 
 (defun rust-get-buffer-pos (pos-symbol)
   "Get buffer position from POS-SYMBOL.
@@ -626,3 +758,38 @@ All positions are position symbols found in `rust-test-positions-alist'."
    'middle-of-struct
    'before-start-of-struct 'after-end-of-struct
    #'mark-defun))
+
+(ert-deftest indent-line-blank-line-motion ()
+  (rust-test-motion
+   rust-test-indent-motion-string
+   'blank-line-indent-start
+   'blank-line-indent-target
+   #'indent-for-tab-command))
+
+(ert-deftest indent-line-closing-brace-motion ()
+  (rust-test-motion
+   rust-test-indent-motion-string
+   'closing-brace-indent-start
+   'closing-brace-indent-target
+   #'indent-for-tab-command))
+
+(ert-deftest indent-line-middle-push-motion ()
+  (rust-test-motion
+   rust-test-indent-motion-string
+   'middle-push-indent-start
+   'middle-push-indent-target
+   #'indent-for-tab-command))
+
+(ert-deftest indent-line-after-whitespace-motion ()
+  (rust-test-motion
+   rust-test-indent-motion-string
+   'after-whitespace-indent-start
+   'after-whitespace-indent-target
+   #'indent-for-tab-command))
+
+(ert-deftest indent-line-middle-pull-motion ()
+  (rust-test-motion
+   rust-test-indent-motion-string
+   'middle-pull-indent-start
+   'middle-pull-indent-target
+   #'indent-for-tab-command))
diff --git a/src/etc/emacs/rust-mode.el b/src/etc/emacs/rust-mode.el
index 4e1c74c31df..b304df8f14c 100644
--- a/src/etc/emacs/rust-mode.el
+++ b/src/etc/emacs/rust-mode.el
@@ -59,70 +59,95 @@
 	(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 or brace (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))))))
-    (cond
-     ;; If we're to the left of the indentation, reindent and jump to it.
-     ((<= (current-column) indent)
-      (indent-line-to indent))
-
-     ;; We're to the right; if it needs indent, do so but save excursion.
-     ((not (eq (current-indentation) indent))
-      (save-excursion (indent-line-to indent))))))
+              (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
+      ;; excursion so that adding the indentations will leave us at the
+      ;; equivalent position within the line to where we were before.
+      (if (<= (current-column) (current-indentation))
+          (indent-line-to indent)
+        (save-excursion (indent-line-to indent))))))
 
 
 ;; Font-locking definitions and helpers