@@ -567,7 +567,7 @@ buffer."
567567 ; ; foo.bar
568568 (t (funcall skip-dot-identifier)))))))
569569
570- (defun rust-mode-indent-line ()
570+ (defun rust-mode-- indent-line ()
571571 (interactive )
572572 (let ((indent
573573 (save-excursion
@@ -769,6 +769,123 @@ buffer."
769769 (save-excursion (= (progn (goto-char pos1) (line-end-position ))
770770 (progn (goto-char pos2) (line-end-position )))))
771771
772+ (defun rust-mode-indent-line ()
773+ " Indent the current line, and indent code examples in comments.
774+
775+ Indent the current line as `rust-mode-indent-line' does. If
776+ point is inside a block comment containing a Markdown code
777+ example (delimited by triple backquotes), then also indent the
778+ current line within the code example."
779+ (interactive )
780+
781+ ; ; First, reindent the current line.
782+ (rust-mode--indent-line)
783+
784+ ; ; If point is inside a comment:
785+ (let ((ppss (syntax-ppss )))
786+ (when (nth 4 ppss)
787+ (rust-with-comment-fill-prefix
788+ (lambda ()
789+ (let* ((orig-buf (current-buffer ))
790+ (orig-point (point ))
791+ (orig-eol (line-end-position ))
792+ (orig-bol (line-beginning-position ))
793+ (orig-mode major-mode)
794+ (com-start (nth 8 ppss))
795+ (com-prefix (replace-regexp-in-string " \\ s-*\\ '" " "
796+ (or fill-prefix " " )))
797+ (com-re (regexp-quote com-prefix))
798+ (cb-re (concat " ^" com-re " \\ (\\ s-*\\ )```" ))
799+ cb-start cb-pad cb-hidden-marker indented rel-point)
800+
801+ ; ; If point is within the prefix (not inside the comment
802+ ; ; body), don't do anything fancy.
803+ (when (>= orig-point (+ orig-bol (length com-prefix)))
804+ (save-excursion
805+ ; ; If we're in a // comment block, use the fill prefix to
806+ ; ; find the start of the block. If we're in a /*
807+ ; ; comment, the start is determined by ppss.
808+ (when (string-match " ^\\ s-*//" com-prefix)
809+ (setq com-start orig-bol)
810+ (while (and (= (forward-line -1 ) 0 )
811+ (looking-at com-re))
812+ (setq com-start (point ))))
813+
814+ ; ; Search for ``` lines within the comment block, and
815+ ; ; identify the start of the current code block if any.
816+ (goto-char com-start)
817+ (while (re-search-forward cb-re orig-bol t )
818+ (setq cb-start (unless cb-start (line-end-position ))
819+ cb-pad (match-string 1 ))))
820+
821+ (when cb-start
822+ ; ; We're inside a code block. Copy preceding contents to
823+ ; ; a temporary buffer.
824+ (with-temp-buffer
825+ (insert-buffer-substring orig-buf cb-start orig-eol)
826+ (forward-char (- orig-point orig-eol))
827+ (save-excursion
828+ ; ; For each line in the temporary buffer, remove
829+ ; ; the comment prefix, left padding if present, and
830+ ; ; hidden-line marker if present. For example, if
831+ ; ; the code block begins with:
832+ ; ;
833+ ; ; ^ /// ```$
834+ ; ;
835+ ; ; then trim lines as follows:
836+ ; ;
837+ ; ; ^ ///$ becomes ^$
838+ ; ; ^ /// let x = 2;$ becomes ^ let x = 2;$
839+ ; ; ^ /// # fn main() {$ becomes ^fn main() {$
840+ ; ;
841+ ; ; If the line we're indenting isn't a hidden line,
842+ ; ; then remove hidden lines completely - non-hidden
843+ ; ; lines are indented as if the hidden lines don't
844+ ; ; exist.
845+ (let ((trim-re (concat com-re " \\ (?:" cb-pad " \\ )?"
846+ " \\ (\\ s-*# \\ )?" )))
847+ (beginning-of-line )
848+ (if (and (looking-at trim-re) (match-beginning 1 ))
849+ (setq cb-hidden-marker " # " )
850+ (setq cb-hidden-marker " "
851+ trim-re (concat com-re " \\ (?:" cb-pad " \\ )?"
852+ " \\ (\\ s-*# .*\\ )?" )))
853+
854+ (goto-char (point-min ))
855+ (while (not (eobp ))
856+ (when (looking-at trim-re)
857+ (delete-region (point ) (match-end 0 )))
858+ (forward-line 1 ))))
859+
860+ ; ; Reindent the line. Copy local settings from the
861+ ; ; parent buffer, but disable indent-tabs-mode unless
862+ ; ; it is enabled in the parent buffer and the code
863+ ; ; block is already tab-aligned.
864+ (funcall orig-mode)
865+ (mapc (lambda (v )
866+ (when (custom-variable-p (or (car-safe v) v))
867+ (if (symbolp v)
868+ (makunbound (make-local-variable v))
869+ (set (make-local-variable (car v)) (cdr v)))))
870+ (buffer-local-variables orig-buf))
871+ (or (string-suffix-p " \t " cb-pad)
872+ (= 0 (length com-prefix) (length cb-pad))
873+ (setq-local indent-tabs-mode nil ))
874+ (rust-mode--indent-line)
875+
876+ ; ; Extract the indented line and copy back into the
877+ ; ; original buffer.
878+ (setq rel-point (- (point ) (point-max )))
879+ (beginning-of-line )
880+ (setq indented
881+ (concat com-prefix cb-pad cb-hidden-marker
882+ (buffer-substring (point ) (point-max )))))
883+ (goto-char orig-eol)
884+ (unless (equal indented (buffer-substring orig-bol orig-eol))
885+ (delete-region orig-bol orig-eol)
886+ (insert indented))
887+ (forward-char rel-point)))))))))
888+
772889; ;; Font-locking definitions and helpers
773890
774891(defun rust-next-string-interpolation (limit )
0 commit comments