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.
This commit is contained in:
commit
780adfffc3
@ -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))
|
||||
|
@ -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))))))))))
|
||||
(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)))
|
||||
|
||||
;; 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))
|
||||
(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
|
||||
|
||||
;; 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))))))
|
||||
;; 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user