@@ -70,34 +70,6 @@ When nil, `where' will be aligned with `fn' or `trait'."
7070 :safe #'booleanp
7171 :group 'rust-mode )
7272
73- (defcustom rust-format-on-save nil
74- " Format future rust buffers before saving using rustfmt."
75- :type 'boolean
76- :safe #'booleanp
77- :group 'rust-mode )
78-
79- (defcustom rust-format-show-buffer t
80- " Show *rustfmt* buffer if formatting detected problems."
81- :type 'boolean
82- :safe #'booleanp
83- :group 'rust-mode )
84-
85- (defcustom rust-format-goto-problem t
86- " Jump to location of first detected problem when formatting buffer."
87- :type 'boolean
88- :safe #'booleanp
89- :group 'rust-mode )
90-
91- (defcustom rust-rustfmt-bin " rustfmt"
92- " Path to rustfmt executable."
93- :type 'string
94- :group 'rust-mode )
95-
96- (defcustom rust-rustfmt-switches '(" --edition" " 2018" )
97- " Arguments to pass when invoking the `rustfmt' executable."
98- :type '(repeat string)
99- :group 'rust-mode )
100-
10173(defcustom rust-cargo-bin " cargo"
10274 " Path to cargo executable."
10375 :type 'string
@@ -1608,314 +1580,6 @@ This is written mainly to be used as `end-of-defun-function' for Rust."
16081580 ; ; There is no opening brace, so consider the whole buffer to be one "defun"
16091581 (goto-char (point-max ))))
16101582
1611- ; ;; Formatting using rustfmt
1612-
1613- (defconst rust-rustfmt-buffername " *rustfmt*" )
1614-
1615- (defun rust--format-call (buf )
1616- " Format BUF using rustfmt."
1617- (with-current-buffer (get-buffer-create rust-rustfmt-buffername)
1618- (view-mode +1 )
1619- (let ((inhibit-read-only t ))
1620- (erase-buffer )
1621- (insert-buffer-substring buf)
1622- (let* ((tmpf (make-temp-file " rustfmt" ))
1623- (ret (apply 'call-process-region
1624- (point-min )
1625- (point-max )
1626- rust-rustfmt-bin
1627- t
1628- `(t , tmpf )
1629- nil
1630- rust-rustfmt-switches)))
1631- (unwind-protect
1632- (cond
1633- ((zerop ret)
1634- (if (not (string= (buffer-string )
1635- (with-current-buffer buf (buffer-string ))))
1636- ; ; replace-buffer-contents was in emacs 26.1, but it
1637- ; ; was broken for non-ASCII strings, so we need 26.2.
1638- (if (and (fboundp 'replace-buffer-contents )
1639- (version<= " 26.2" emacs-version))
1640- (with-current-buffer buf
1641- (replace-buffer-contents rust-rustfmt-buffername))
1642- (copy-to-buffer buf (point-min ) (point-max ))))
1643- (kill-buffer ))
1644- ((= ret 3 )
1645- (if (not (string= (buffer-string )
1646- (with-current-buffer buf (buffer-string ))))
1647- (copy-to-buffer buf (point-min ) (point-max )))
1648- (erase-buffer )
1649- (insert-file-contents tmpf)
1650- (rust--format-fix-rustfmt-buffer (buffer-name buf))
1651- (error " Rustfmt could not format some lines, see *rustfmt* buffer for details " ))
1652- (t
1653- (erase-buffer )
1654- (insert-file-contents tmpf)
1655- (rust--format-fix-rustfmt-buffer (buffer-name buf))
1656- (error " Rustfmt failed, see *rustfmt* buffer for details " ))))
1657- (delete-file tmpf)))))
1658-
1659- ; ; Since we run rustfmt through stdin we get <stdin> markers in the
1660- ; ; output. This replaces them with the buffer name instead.
1661- (defun rust--format-fix-rustfmt-buffer (buffer-name )
1662- (with-current-buffer (get-buffer rust-rustfmt-buffername)
1663- (let ((inhibit-read-only t ))
1664- (goto-char (point-min ))
1665- (while (re-search-forward " --> <stdin>:" nil t )
1666- (replace-match (format " --> %s : " buffer-name)))
1667- (while (re-search-forward " --> stdin:" nil t )
1668- (replace-match (format " --> %s : " buffer-name))))))
1669-
1670- ; ; If rust-mode has been configured to navigate to source of the error
1671- ; ; or display it, do so -- and return true. Otherwise return nil to
1672- ; ; indicate nothing was done.
1673- (defun rust--format-error-handler ()
1674- (let ((ok nil ))
1675- (when rust-format-show-buffer
1676- (display-buffer (get-buffer rust-rustfmt-buffername))
1677- (setq ok t ))
1678- (when rust-format-goto-problem
1679- (rust-goto-format-problem)
1680- (setq ok t ))
1681- ok))
1682-
1683- (defun rust-goto-format-problem ()
1684- " Jumps to problem reported by rustfmt, if any.
1685-
1686- In case of multiple problems cycles through them. Displays the
1687- rustfmt complain in the echo area."
1688- (interactive )
1689- ; ; This uses position in *rustfmt* buffer to know which is the next
1690- ; ; error to jump to, and source: line in the buffer to figure which
1691- ; ; buffer it is from.
1692- (let ((rustfmt (get-buffer rust-rustfmt-buffername)))
1693- (if (not rustfmt)
1694- (message " No *rustfmt*, no problems. " )
1695- (let ((target-buffer (with-current-buffer rustfmt
1696- (save-excursion
1697- (goto-char (point-min ))
1698- (when (re-search-forward " --> \\ ([^:]+\\ ):" nil t )
1699- (match-string 1 )))))
1700- (target-point (with-current-buffer rustfmt
1701- ; ; No save-excursion, this is how we cycle through!
1702- (let ((regex " --> [^:]+:\\ ([0-9]+\\ ):\\ ([0-9]+\\ )" ))
1703- (when (or (re-search-forward regex nil t )
1704- (progn (goto-char (point-min ))
1705- (re-search-forward regex nil t )))
1706- (cons (string-to-number (match-string 1 ))
1707- (string-to-number (match-string 2 )))))))
1708- (target-problem (with-current-buffer rustfmt
1709- (save-excursion
1710- (when (re-search-backward " ^error:.+\n " nil t )
1711- (forward-char (length " error: " ))
1712- (let ((p0 (point )))
1713- (if (re-search-forward " \n error:.+\n " nil t )
1714- (buffer-substring p0 (point ))
1715- (buffer-substring p0 (point-max )))))))))
1716- (when (and target-buffer (get-buffer target-buffer) target-point)
1717- (switch-to-buffer target-buffer)
1718- (goto-char (point-min ))
1719- (forward-line (1- (car target-point)))
1720- (forward-char (1- (cdr target-point))))
1721- (message target-problem)))))
1722-
1723- (defconst rust--format-word " \
1724- \\ b\\ (else\\ |enum\\ |fn\\ |for\\ |if\\ |let\\ |loop\\ |\
1725- match\\ |struct\\ |union\\ |unsafe\\ |while\\ )\\ b" )
1726- (defconst rust--format-line " \\ ([\n ]\\ )" )
1727-
1728- ; ; Counts number of matches of regex beginning up to max-beginning,
1729- ; ; leaving the point at the beginning of the last match.
1730- (defun rust--format-count (regex max-beginning )
1731- (let ((count 0 )
1732- save-point
1733- beginning)
1734- (while (and (< (point ) max-beginning)
1735- (re-search-forward regex max-beginning t ))
1736- (setq count (1+ count))
1737- (setq beginning (match-beginning 1 )))
1738- ; ; try one more in case max-beginning lies in the middle of a match
1739- (setq save-point (point ))
1740- (when (re-search-forward regex nil t )
1741- (let ((try-beginning (match-beginning 1 )))
1742- (if (> try-beginning max-beginning)
1743- (goto-char save-point)
1744- (setq count (1+ count))
1745- (setq beginning try-beginning))))
1746- (when beginning (goto-char beginning))
1747- count))
1748-
1749- ; ; Gets list describing pos or (point).
1750- ; ; The list contains:
1751- ; ; 1. the number of matches of rust--format-word,
1752- ; ; 2. the number of matches of rust--format-line after that,
1753- ; ; 3. the number of columns after that.
1754- (defun rust--format-get-loc (buffer &optional pos )
1755- (with-current-buffer buffer
1756- (save-excursion
1757- (let ((pos (or pos (point )))
1758- words lines columns)
1759- (goto-char (point-min ))
1760- (setq words (rust--format-count rust--format-word pos))
1761- (setq lines (rust--format-count rust--format-line pos))
1762- (if (> lines 0 )
1763- (if (= (point ) pos)
1764- (setq columns -1 )
1765- (forward-char 1 )
1766- (goto-char pos)
1767- (setq columns (current-column )))
1768- (let ((initial-column (current-column )))
1769- (goto-char pos)
1770- (setq columns (- (current-column ) initial-column))))
1771- (list words lines columns)))))
1772-
1773- ; ; Moves the point forward by count matches of regex up to max-pos,
1774- ; ; and returns new max-pos making sure final position does not include another match.
1775- (defun rust--format-forward (regex count max-pos )
1776- (when (< (point ) max-pos)
1777- (let ((beginning (point )))
1778- (while (> count 0 )
1779- (setq count (1- count))
1780- (re-search-forward regex nil t )
1781- (setq beginning (match-beginning 1 )))
1782- (when (re-search-forward regex nil t )
1783- (setq max-pos (min max-pos (match-beginning 1 ))))
1784- (goto-char beginning)))
1785- max-pos)
1786-
1787- ; ; Gets the position from a location list obtained using rust--format-get-loc.
1788- (defun rust--format-get-pos (buffer loc )
1789- (with-current-buffer buffer
1790- (save-excursion
1791- (goto-char (point-min ))
1792- (let ((max-pos (point-max ))
1793- (words (pop loc))
1794- (lines (pop loc))
1795- (columns (pop loc)))
1796- (setq max-pos (rust--format-forward rust--format-word words max-pos))
1797- (setq max-pos (rust--format-forward rust--format-line lines max-pos))
1798- (when (> lines 0 ) (forward-char ))
1799- (let ((initial-column (current-column ))
1800- (save-point (point )))
1801- (move-end-of-line nil )
1802- (when (> (current-column ) (+ initial-column columns))
1803- (goto-char save-point)
1804- (forward-char columns)))
1805- (min (point ) max-pos)))))
1806-
1807- (defun rust-format-diff-buffer ()
1808- " Show diff to current buffer from rustfmt.
1809-
1810- Return the created process."
1811- (interactive )
1812- (unless (executable-find rust-rustfmt-bin)
1813- (error " Could not locate executable \% s\" " rust-rustfmt-bin))
1814- (let* ((buffer
1815- (with-current-buffer
1816- (get-buffer-create " *rustfmt-diff*" )
1817- (let ((inhibit-read-only t ))
1818- (erase-buffer ))
1819- (current-buffer )))
1820- (proc
1821- (apply 'start-process
1822- " rustfmt-diff"
1823- buffer
1824- rust-rustfmt-bin
1825- " --check"
1826- (cons (buffer-file-name )
1827- rust-rustfmt-switches))))
1828- (set-process-sentinel proc 'rust-format-diff-buffer-sentinel )
1829- proc))
1830-
1831- (defun rust-format-diff-buffer-sentinel (process _e )
1832- (when (eq 'exit (process-status process))
1833- (if (> (process-exit-status process) 0 )
1834- (with-current-buffer " *rustfmt-diff*"
1835- (let ((inhibit-read-only t ))
1836- (diff-mode ))
1837- (pop-to-buffer (current-buffer )))
1838- (message " rustfmt check passed. " ))))
1839-
1840- (defun rust--format-buffer-using-replace-buffer-contents ()
1841- (condition-case err
1842- (progn
1843- (rust--format-call (current-buffer ))
1844- (message " Formatted buffer with rustfmt. " ))
1845- (error
1846- (or (rust--format-error-handler)
1847- (signal (car err) (cdr err))))))
1848-
1849- (defun rust--format-buffer-saving-position-manually ()
1850- (let* ((current (current-buffer ))
1851- (base (or (buffer-base-buffer current) current))
1852- buffer-loc
1853- window-loc)
1854- (dolist (buffer (buffer-list ))
1855- (when (or (eq buffer base)
1856- (eq (buffer-base-buffer buffer) base))
1857- (push (list buffer
1858- (rust--format-get-loc buffer nil ))
1859- buffer-loc)))
1860- (dolist (frame (frame-list ))
1861- (dolist (window (window-list frame))
1862- (let ((buffer (window-buffer window)))
1863- (when (or (eq buffer base)
1864- (eq (buffer-base-buffer buffer) base))
1865- (let ((start (window-start window))
1866- (point (window-point window)))
1867- (push (list window
1868- (rust--format-get-loc buffer start)
1869- (rust--format-get-loc buffer point))
1870- window-loc))))))
1871- (condition-case err
1872- (unwind-protect
1873- ; ; save and restore window start position
1874- ; ; after reformatting
1875- ; ; to avoid the disturbing scrolling
1876- (let ((w-start (window-start )))
1877- (rust--format-call (current-buffer ))
1878- (set-window-start (selected-window ) w-start)
1879- (message " Formatted buffer with rustfmt. " ))
1880- (dolist (loc buffer-loc)
1881- (let* ((buffer (pop loc))
1882- (pos (rust--format-get-pos buffer (pop loc))))
1883- (with-current-buffer buffer
1884- (goto-char pos))))
1885- (dolist (loc window-loc)
1886- (let* ((window (pop loc))
1887- (buffer (window-buffer window))
1888- (start (rust--format-get-pos buffer (pop loc)))
1889- (pos (rust--format-get-pos buffer (pop loc))))
1890- (unless (eq buffer current)
1891- (set-window-start window start))
1892- (set-window-point window pos))))
1893- (error
1894- (or (rust--format-error-handler)
1895- (signal (car err) (cdr err)))))))
1896-
1897- (defun rust-format-buffer ()
1898- " Format the current buffer using rustfmt."
1899- (interactive )
1900- (unless (executable-find rust-rustfmt-bin)
1901- (error " Could not locate executable \" %s \" " rust-rustfmt-bin))
1902- ; ; If emacs version >= 26.2, we can use replace-buffer-contents to
1903- ; ; preserve location and markers in buffer, otherwise we can try to
1904- ; ; save locations as best we can, though we still lose markers.
1905- (if (version<= " 26.2" emacs-version)
1906- (rust--format-buffer-using-replace-buffer-contents)
1907- (rust--format-buffer-saving-position-manually)))
1908-
1909- (defun rust-enable-format-on-save ()
1910- " Enable formatting using rustfmt when saving buffer."
1911- (interactive )
1912- (setq-local rust-format-on-save t ))
1913-
1914- (defun rust-disable-format-on-save ()
1915- " Disable formatting using rustfmt when saving buffer."
1916- (interactive )
1917- (setq-local rust-format-on-save nil ))
1918-
19191583(defun rust--compile (format-string &rest args )
19201584 (when (null rust-buffer-project)
19211585 (rust-update-buffer-project))
@@ -1955,26 +1619,6 @@ Return the created process."
19551619 (interactive )
19561620 (rust--compile " %s test" rust-cargo-bin))
19571621
1958- ; ;; Hooks
1959-
1960- (defun rust-before-save-hook ()
1961- (when rust-format-on-save
1962- (condition-case e
1963- (rust-format-buffer)
1964- (error (format " rust-before-save-hook: %S %S "
1965- (car e)
1966- (cdr e))))))
1967-
1968- (defun rust-after-save-hook ()
1969- (when rust-format-on-save
1970- (if (not (executable-find rust-rustfmt-bin))
1971- (error " Could not locate executable \" %s \" " rust-rustfmt-bin)
1972- (when (get-buffer rust-rustfmt-buffername)
1973- ; ; KLDUGE: re-run the error handlers -- otherwise message area
1974- ; ; would show "Wrote ..." instead of the error description.
1975- (or (rust--format-error-handler)
1976- (message " rustfmt detected problems, see *rustfmt* for more. " ))))))
1977-
19781622; ;; Secondary Commands
19791623
19801624(defun rust-playpen-region (begin end )
0 commit comments