|
59 | 59 | (backward-word 1))
|
60 | 60 | (current-column))))
|
61 | 61 |
|
| 62 | +(defun rust-rewind-to-beginning-of-current-level-expr () |
| 63 | + (let ((current-level (rust-paren-level))) |
| 64 | + (back-to-indentation) |
| 65 | + (while (> (rust-paren-level) current-level) |
| 66 | + (backward-up-list) |
| 67 | + (back-to-indentation)))) |
| 68 | + |
62 | 69 | (defun rust-mode-indent-line ()
|
63 | 70 | (interactive)
|
64 | 71 | (let ((indent
|
65 | 72 | (save-excursion
|
66 | 73 | (back-to-indentation)
|
67 |
| - (let ((level (rust-paren-level))) |
| 74 | + ;; Point is now at beginning of current line |
| 75 | + (let* ((level (rust-paren-level)) |
| 76 | + (baseline |
| 77 | + ;; Our "baseline" is one level out from the indentation of the expression |
| 78 | + ;; containing the innermost enclosing opening bracket. That |
| 79 | + ;; way if we are within a block that has a different |
| 80 | + ;; indentation than this mode would give it, we still indent |
| 81 | + ;; the inside of it correctly relative to the outside. |
| 82 | + (if (= 0 level) |
| 83 | + 0 |
| 84 | + (save-excursion |
| 85 | + (backward-up-list) |
| 86 | + (rust-rewind-to-beginning-of-current-level-expr) |
| 87 | + (+ (current-column) rust-indent-offset))))) |
68 | 88 | (cond
|
69 | 89 | ;; A function return type is indented to the corresponding function arguments
|
70 | 90 | ((looking-at "->")
|
71 | 91 | (save-excursion
|
72 | 92 | (backward-list)
|
73 | 93 | (or (rust-align-to-expr-after-brace)
|
74 |
| - (* rust-indent-offset (+ 1 level))))) |
| 94 | + (+ baseline rust-indent-offset)))) |
75 | 95 |
|
76 | 96 | ;; A closing brace is 1 level unindended
|
77 |
| - ((looking-at "}") (* rust-indent-offset (- level 1))) |
| 97 | + ((looking-at "}") (- baseline rust-indent-offset)) |
78 | 98 |
|
79 | 99 | ;; Doc comments in /** style with leading * indent to line up the *s
|
80 | 100 | ((and (nth 4 (syntax-ppss)) (looking-at "*"))
|
81 |
| - (+ 1 (* rust-indent-offset level))) |
| 101 | + (+ 1 baseline)) |
82 | 102 |
|
83 | 103 | ;; If we're in any other token-tree / sexp, then:
|
84 |
| - ;; - [ or ( means line up with the opening token |
85 |
| - ;; - { means indent to either nesting-level * rust-indent-offset, |
86 |
| - ;; or one further indent from that if either current line |
87 |
| - ;; begins with 'else', or previous line didn't end in |
88 |
| - ;; semi, comma, brace or single pipe (other than whitespace and line |
89 |
| - ;; comments) , and wasn't an attribute. But if we have |
90 |
| - ;; something after the open brace and ending with a comma, |
91 |
| - ;; treat it as fields and align them. PHEW. |
92 |
| - ((> level 0) |
93 |
| - (let ((pt (point))) |
94 |
| - (rust-rewind-irrelevant) |
95 |
| - (backward-up-list) |
96 |
| - (or (and (looking-at "[[({]") |
97 |
| - (rust-align-to-expr-after-brace)) |
98 |
| - (progn |
99 |
| - (goto-char pt) |
100 |
| - (back-to-indentation) |
101 |
| - (if (looking-at "\\<else\\>") |
102 |
| - (* rust-indent-offset (+ 1 level)) |
103 |
| - (progn |
104 |
| - (goto-char pt) |
105 |
| - (beginning-of-line) |
106 |
| - (rust-rewind-irrelevant) |
107 |
| - (end-of-line) |
108 |
| - (if (looking-back "\\(?:[(,:;?[{}]\\|[^|]|\\)[[:space:]]*\\(?://.*\\)?") |
109 |
| - (* rust-indent-offset level) |
110 |
| - (back-to-indentation) |
111 |
| - (if (looking-at "#") |
112 |
| - (* rust-indent-offset level) |
113 |
| - (* rust-indent-offset (+ 1 level)))))))))) |
114 |
| - |
115 |
| - ;; Otherwise we're in a column-zero definition |
116 |
| - (t 0)))))) |
| 104 | + (t |
| 105 | + (or |
| 106 | + ;; If we are inside a pair of braces, with something after the |
| 107 | + ;; open brace on the same line and ending with a comma, treat |
| 108 | + ;; it as fields and align them. |
| 109 | + (when (> level 0) |
| 110 | + (save-excursion |
| 111 | + (rust-rewind-irrelevant) |
| 112 | + (backward-up-list) |
| 113 | + ;; Point is now at the beginning of the containing set of braces |
| 114 | + (rust-align-to-expr-after-brace))) |
| 115 | + |
| 116 | + (progn |
| 117 | + (back-to-indentation) |
| 118 | + ;; Point is now at the beginning of the current line |
| 119 | + (if (or |
| 120 | + ;; If this line begins with "else" or "{", stay on the |
| 121 | + ;; baseline as well (we are continuing an expression, |
| 122 | + ;; but the "else" or "{" should align with the beginning |
| 123 | + ;; of the expression it's in.) |
| 124 | + (looking-at "\\<else\\>\\|{") |
| 125 | + |
| 126 | + (save-excursion |
| 127 | + (rust-rewind-irrelevant) |
| 128 | + ;; Point is now at the end of the previous ine |
| 129 | + (or |
| 130 | + ;; If we are at the first line, no indentation is needed, so stay at baseline... |
| 131 | + (= 1 (line-number-at-pos (point))) |
| 132 | + ;; ..or if the previous line ends with any of these: |
| 133 | + ;; { ? : ( , ; [ } |
| 134 | + ;; then we are at the beginning of an expression, so stay on the baseline... |
| 135 | + (looking-back "[(,:;?[{}]\\|[^|]|") |
| 136 | + ;; or if the previous line is the end of an attribute, stay at the baseline... |
| 137 | + (progn (rust-rewind-to-beginning-of-current-level-expr) (looking-at "#"))))) |
| 138 | + baseline |
| 139 | + |
| 140 | + ;; Otherwise, we are continuing the same expression from the previous line, |
| 141 | + ;; so add one additional indent level |
| 142 | + (+ baseline rust-indent-offset)))))))))) |
117 | 143 | (when (not (eq (current-indentation) indent))
|
118 | 144 | ;; If we're at the beginning of the line (before or at the current
|
119 | 145 | ;; indentation), jump with the indentation change. Otherwise, save the
|
|
0 commit comments