Skip to content

Commit 22c8cfa

Browse files
committed
Merge pull request #43 from MicahChalmer/indent-backslash-strings
Indent inside strings after line-ending backslash
2 parents 249e3ce + 52febe9 commit 22c8cfa

File tree

2 files changed

+178
-10
lines changed

2 files changed

+178
-10
lines changed

rust-mode-tests.el

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,8 @@ very very very long string
284284
*/"
285285
))
286286

287-
(defun test-indent (indented)
288-
(let ((deindented (replace-regexp-in-string "^[[:blank:]]*" " " indented)))
287+
(defun test-indent (indented &optional deindented)
288+
(let ((deindented (or deindented (replace-regexp-in-string "^[[:blank:]]*" " " indented))))
289289
(rust-test-manip-code
290290
deindented
291291
1
@@ -1207,3 +1207,122 @@ impl Foo for Bar {
12071207
}
12081208
"
12091209
))
1210+
1211+
(ert-deftest test-indent-string-with-eol-backslash ()
1212+
(test-indent
1213+
"
1214+
pub fn foo() {
1215+
format!(\"abc \\
1216+
def\")
1217+
}
1218+
"
1219+
))
1220+
1221+
(ert-deftest test-indent-string-with-eol-backslash-at-start ()
1222+
(test-indent
1223+
"
1224+
pub fn foo() {
1225+
format!(\"\\
1226+
abc \\
1227+
def\")
1228+
}
1229+
"
1230+
))
1231+
1232+
(ert-deftest test-indent-string-without-eol-backslash-indent-is-not-touched ()
1233+
(test-indent
1234+
"
1235+
pub fn foo() {
1236+
format!(\"
1237+
abc
1238+
def\");
1239+
}
1240+
1241+
pub fn foo() {
1242+
format!(\"la la la
1243+
la
1244+
la la\");
1245+
}
1246+
"
1247+
;; Should still indent the code parts but leave the string internals alone:
1248+
"
1249+
pub fn foo() {
1250+
format!(\"
1251+
abc
1252+
def\");
1253+
}
1254+
1255+
pub fn foo() {
1256+
format!(\"la la la
1257+
la
1258+
la la\");
1259+
}
1260+
"
1261+
))
1262+
1263+
(ert-deftest test-indent-string-eol-backslash-mixed-with-literal-eol ()
1264+
(test-indent
1265+
"
1266+
fn foo() {
1267+
println!(\"
1268+
Here is the beginning of the string
1269+
and here is a line that is arbitrarily indented \\
1270+
and a continuation of that indented line
1271+
and another arbitrary indentation
1272+
still another
1273+
yet another \\
1274+
with a line continuing it
1275+
And another line not indented
1276+
\")
1277+
}
1278+
"
1279+
"
1280+
fn foo() {
1281+
println!(\"
1282+
Here is the beginning of the string
1283+
and here is a line that is arbitrarily indented \\
1284+
and a continuation of that indented line
1285+
and another arbitrary indentation
1286+
still another
1287+
yet another \\
1288+
with a line continuing it
1289+
And another line not indented
1290+
\")
1291+
}
1292+
"))
1293+
1294+
(ert-deftest test-indent-string-eol-backslash-dont-touch-raw-strings ()
1295+
(test-indent
1296+
"
1297+
pub fn foo() {
1298+
format!(r\"\
1299+
abc\
1300+
def\");
1301+
}
1302+
1303+
pub fn foo() {
1304+
format!(r\"la la la
1305+
la\
1306+
la la\");
1307+
}
1308+
"
1309+
;; Should still indent the code parts but leave the string internals alone:
1310+
"
1311+
pub fn foo() {
1312+
format!(r\"\
1313+
abc\
1314+
def\");
1315+
}
1316+
1317+
pub fn foo() {
1318+
format!(r\"la la la
1319+
la\
1320+
la la\");
1321+
}
1322+
"
1323+
))
1324+
1325+
(ert-deftest indent-inside-string-first-line ()
1326+
(test-indent
1327+
;; Needs to leave 1 space before "world"
1328+
"\"hello \\\n world\""))

rust-mode.el

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
;; be undone via tab.
118118

119119
(when (looking-at (concat "\s*\." rust-re-ident))
120-
(previous-logical-line)
120+
(forward-line -1)
121121
(end-of-line)
122122

123123
(let
@@ -164,10 +164,58 @@
164164
(when rust-indent-method-chain
165165
(rust-align-to-method-chain))
166166
(save-excursion
167+
(rust-rewind-irrelevant)
167168
(backward-up-list)
168169
(rust-rewind-to-beginning-of-current-level-expr)
169170
(+ (current-column) rust-indent-offset))))))
170171
(cond
172+
;; Indent inside a non-raw string only if the the previous line
173+
;; ends with a backslash that is is inside the same string
174+
((nth 3 (syntax-ppss))
175+
(let*
176+
((string-begin-pos (nth 8 (syntax-ppss)))
177+
(end-of-prev-line-pos (when (> (line-number-at-pos) 1)
178+
(save-excursion
179+
(forward-line -1)
180+
(end-of-line)
181+
(point)))))
182+
(when
183+
(and
184+
;; If the string begins with an "r" it's a raw string and
185+
;; we should not change the indentation
186+
(/= ?r (char-after string-begin-pos))
187+
188+
;; If we're on the first line this will be nil and the
189+
;; rest does not apply
190+
end-of-prev-line-pos
191+
192+
;; The end of the previous line needs to be inside the
193+
;; current string...
194+
(> end-of-prev-line-pos string-begin-pos)
195+
196+
;; ...and end with a backslash
197+
(= ?\\ (char-before end-of-prev-line-pos)))
198+
199+
;; Indent to the same level as the previous line, or the
200+
;; start of the string if the previous line starts the string
201+
(if (= (line-number-at-pos end-of-prev-line-pos) (line-number-at-pos string-begin-pos))
202+
;; The previous line is the start of the string.
203+
;; If the backslash is the only character after the
204+
;; string beginning, indent to the next indent
205+
;; level. Otherwise align with the start of the string.
206+
(if (> (- end-of-prev-line-pos string-begin-pos) 2)
207+
(save-excursion
208+
(goto-char (+ 1 string-begin-pos))
209+
(current-column))
210+
baseline)
211+
212+
;; The previous line is not the start of the string, so
213+
;; match its indentation.
214+
(save-excursion
215+
(goto-char end-of-prev-line-pos)
216+
(back-to-indentation)
217+
(current-column))))))
218+
171219
;; A function return type is indented to the corresponding function arguments
172220
((looking-at "->")
173221
(save-excursion
@@ -223,13 +271,14 @@
223271
;; so add one additional indent level
224272
(+ baseline rust-indent-offset))))))))))
225273

226-
;; If we're at the beginning of the line (before or at the current
227-
;; indentation), jump with the indentation change. Otherwise, save the
228-
;; excursion so that adding the indentations will leave us at the
229-
;; equivalent position within the line to where we were before.
230-
(if (<= (current-column) (current-indentation))
231-
(indent-line-to indent)
232-
(save-excursion (indent-line-to indent)))))
274+
(when indent
275+
;; If we're at the beginning of the line (before or at the current
276+
;; indentation), jump with the indentation change. Otherwise, save the
277+
;; excursion so that adding the indentations will leave us at the
278+
;; equivalent position within the line to where we were before.
279+
(if (<= (current-column) (current-indentation))
280+
(indent-line-to indent)
281+
(save-excursion (indent-line-to indent))))))
233282

234283

235284
;; Font-locking definitions and helpers

0 commit comments

Comments
 (0)