@@ -567,7 +567,7 @@ buffer."
567
567
; ; foo.bar
568
568
(t (funcall skip-dot-identifier)))))))
569
569
570
- (defun rust-mode-indent-line ()
570
+ (defun rust-mode-- indent-line ()
571
571
(interactive )
572
572
(let ((indent
573
573
(save-excursion
@@ -769,6 +769,123 @@ buffer."
769
769
(save-excursion (= (progn (goto-char pos1) (line-end-position ))
770
770
(progn (goto-char pos2) (line-end-position )))))
771
771
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
+
772
889
; ;; Font-locking definitions and helpers
773
890
774
891
(defun rust-next-string-interpolation (limit )
0 commit comments