@@ -1281,6 +1281,88 @@ This is written mainly to be used as `end-of-defun-function' for Rust."
1281
1281
(kill-buffer ))
1282
1282
(error " Rustfmt failed, see *rustfmt* buffer for details " ))))
1283
1283
1284
+ (defconst rust--format-word " \\ b\\ (else\\ |enum\\ |fn\\ |for\\ |if\\ |let\\ |loop\\ |match\\ |struct\\ |unsafe\\ |while\\ )\\ b" )
1285
+ (defconst rust--format-line " \\ ([\n ]\\ )" )
1286
+
1287
+ ; ; Counts number of matches of regex beginning up to max-beginning,
1288
+ ; ; leaving the point at the beginning of the last match.
1289
+ (defun rust--format-count (regex max-beginning )
1290
+ (let ((count 0 )
1291
+ save-point
1292
+ beginning)
1293
+ (while (and (< (point ) max-beginning)
1294
+ (re-search-forward regex max-beginning t ))
1295
+ (setq count (1+ count))
1296
+ (setq beginning (match-beginning 1 )))
1297
+ ; ; try one more in case max-beginning lies in the middle of a match
1298
+ (setq save-point (point ))
1299
+ (when (re-search-forward regex nil t )
1300
+ (let ((try-beginning (match-beginning 1 )))
1301
+ (if (> try-beginning max-beginning)
1302
+ (goto-char save-point)
1303
+ (setq count (1+ count))
1304
+ (setq beginning try-beginning))))
1305
+ (when beginning (goto-char beginning))
1306
+ count))
1307
+
1308
+ ; ; Gets list describing pos or (point).
1309
+ ; ; The list contains:
1310
+ ; ; 1. the number of matches of rust--format-word,
1311
+ ; ; 2. the number of matches of rust--format-line after that,
1312
+ ; ; 3. the number of columns after that.
1313
+ (defun rust--format-get-loc (buffer &optional pos )
1314
+ (with-current-buffer buffer
1315
+ (save-excursion
1316
+ (let ((pos (or pos (point )))
1317
+ words lines columns)
1318
+ (goto-char (point-min ))
1319
+ (setq words (rust--format-count rust--format-word pos))
1320
+ (setq lines (rust--format-count rust--format-line pos))
1321
+ (if (> lines 0 )
1322
+ (if (= (point ) pos)
1323
+ (setq columns -1 )
1324
+ (forward-char 1 )
1325
+ (goto-char pos)
1326
+ (setq columns (current-column )))
1327
+ (let ((initial-column (current-column )))
1328
+ (goto-char pos)
1329
+ (setq columns (- (current-column ) initial-column))))
1330
+ (list words lines columns)))))
1331
+
1332
+ ; ; Moves the point forward by count matches of regex up to max-pos,
1333
+ ; ; and returns new max-pos making sure final position does not include another match.
1334
+ (defun rust--format-forward (regex count max-pos )
1335
+ (when (< (point ) max-pos)
1336
+ (let ((beginning (point )))
1337
+ (while (> count 0 )
1338
+ (setq count (1- count))
1339
+ (re-search-forward regex nil t )
1340
+ (setq beginning (match-beginning 1 )))
1341
+ (when (re-search-forward regex nil t )
1342
+ (setq max-pos (min max-pos (match-beginning 1 ))))
1343
+ (goto-char beginning)))
1344
+ max-pos)
1345
+
1346
+ ; ; Gets the position from a location list obtained using rust--format-get-loc.
1347
+ (defun rust--format-get-pos (buffer loc )
1348
+ (with-current-buffer buffer
1349
+ (save-excursion
1350
+ (goto-char (point-min ))
1351
+ (let ((max-pos (point-max ))
1352
+ (words (pop loc))
1353
+ (lines (pop loc))
1354
+ (columns (pop loc)))
1355
+ (setq max-pos (rust--format-forward rust--format-word words max-pos))
1356
+ (setq max-pos (rust--format-forward rust--format-line lines max-pos))
1357
+ (when (> lines 0 ) (forward-char ))
1358
+ (let ((initial-column (current-column ))
1359
+ (save-point (point )))
1360
+ (move-end-of-line nil )
1361
+ (when (> (current-column ) (+ initial-column columns))
1362
+ (goto-char save-point)
1363
+ (forward-char columns)))
1364
+ (min (point ) max-pos)))))
1365
+
1284
1366
(defun rust-format-buffer ()
1285
1367
" Format the current buffer using rustfmt."
1286
1368
(interactive )
@@ -1289,58 +1371,37 @@ This is written mainly to be used as `end-of-defun-function' for Rust."
1289
1371
1290
1372
(let* ((current (current-buffer ))
1291
1373
(base (or (buffer-base-buffer current) current))
1292
- buffer-pos
1293
- window-pos )
1374
+ buffer-loc
1375
+ window-loc )
1294
1376
(dolist (buffer (buffer-list ))
1295
1377
(when (or (eq buffer base)
1296
1378
(eq (buffer-base-buffer buffer) base))
1297
- (with-current-buffer buffer
1298
- (push (list buffer
1299
- (line-number-at-pos )
1300
- (current-column ))
1301
- buffer-pos))))
1379
+ (push (list buffer
1380
+ (rust--format-get-loc buffer nil ))
1381
+ buffer-loc)))
1302
1382
(dolist (window (window-list ))
1303
1383
(let ((buffer (window-buffer window)))
1304
1384
(when (or (eq buffer base)
1305
1385
(eq (buffer-base-buffer buffer) base))
1306
1386
(let ((start (window-start window))
1307
1387
(point (window-point window)))
1308
- (with-current-buffer buffer
1309
- (push (list window
1310
- (line-number-at-pos start)
1311
- (save-excursion (goto-char start) (current-column ))
1312
- (line-number-at-pos point)
1313
- (save-excursion (goto-char point) (current-column )))
1314
- window-pos))))))
1315
- (rust--format-call current)
1316
- (dolist (pos buffer-pos)
1317
- (let ((buffer (pop pos))
1318
- (line (pop pos))
1319
- (column (pop pos)))
1388
+ (push (list window
1389
+ (rust--format-get-loc buffer start)
1390
+ (rust--format-get-loc buffer point))
1391
+ window-loc)))))
1392
+ (rust--format-call (current-buffer ))
1393
+ (dolist (loc buffer-loc)
1394
+ (let* ((buffer (pop loc))
1395
+ (pos (rust--format-get-pos buffer (pop loc))))
1320
1396
(with-current-buffer buffer
1321
- ; ; Move to the same line and column as before. This is best
1322
- ; ; effort: if rustfmt inserted lines before point, we end up in
1323
- ; ; the wrong place. See issue #162.
1324
- (goto-char (point-min ))
1325
- (forward-line (1- line))
1326
- (forward-char column))))
1327
- (dolist (pos window-pos)
1328
- (let ((window (pop pos))
1329
- (start-line (pop pos))
1330
- (start-column (pop pos))
1331
- (point-line (pop pos))
1332
- (point-column (pop pos)))
1333
- (with-current-buffer (window-buffer window)
1334
- (let ((start (save-excursion (goto-char (point-min ))
1335
- (forward-line (1- start-line))
1336
- (forward-char start-column)
1337
- (point )))
1338
- (point (save-excursion (goto-char (point-min ))
1339
- (forward-line (1- point-line))
1340
- (forward-char point-column)
1341
- (point ))))
1342
- (set-window-start window start)
1343
- (set-window-point window point))))))
1397
+ (goto-char pos))))
1398
+ (dolist (loc window-loc)
1399
+ (let* ((window (pop loc))
1400
+ (buffer (window-buffer window))
1401
+ (start (rust--format-get-pos buffer (pop loc)))
1402
+ (pos (rust--format-get-pos buffer (pop loc))))
1403
+ (set-window-start window start)
1404
+ (set-window-point window pos))))
1344
1405
1345
1406
; ; Issue #127: Running this on a buffer acts like a revert, and could cause
1346
1407
; ; the fontification to get out of sync. Call the same hook to ensure it is
0 commit comments