2 use std
::string
::String
;
5 use crate::clean
::{self, DocFragment, Item}
;
6 use crate::core
::DocContext
;
7 use crate::fold
::{self, DocFolder}
;
8 use crate::passes
::Pass
;
13 pub const UNINDENT_COMMENTS
: Pass
= Pass
{
14 name
: "unindent-comments",
15 run
: unindent_comments
,
16 description
: "removes excess indentation on comments in order for markdown to like it",
19 pub fn unindent_comments(krate
: clean
::Crate
, _
: &DocContext
<'_
>) -> clean
::Crate
{
20 CommentCleaner
.fold_crate(krate
)
23 struct CommentCleaner
;
25 impl fold
::DocFolder
for CommentCleaner
{
26 fn fold_item(&mut self, mut i
: Item
) -> Option
<Item
> {
27 i
.attrs
.unindent_doc_comments();
28 self.fold_item_recur(i
)
32 impl clean
::Attributes
{
33 pub fn unindent_doc_comments(&mut self) {
34 unindent_fragments(&mut self.doc_strings
);
38 fn unindent_fragments(docs
: &mut Vec
<DocFragment
>) {
39 for fragment
in docs
{
41 DocFragment
::SugaredDoc(_
, _
, ref mut doc_string
)
42 | DocFragment
::RawDoc(_
, _
, ref mut doc_string
)
43 | DocFragment
::Include(_
, _
, _
, ref mut doc_string
) => {
44 *doc_string
= unindent(doc_string
)
50 fn unindent(s
: &str) -> String
{
51 let lines
= s
.lines().collect
::<Vec
<&str>>();
52 let mut saw_first_line
= false;
53 let mut saw_second_line
= false;
54 let min_indent
= lines
.iter().fold(usize::MAX
, |min_indent
, line
| {
55 // After we see the first non-whitespace line, look at
56 // the line we have. If it is not whitespace, and therefore
57 // part of the first paragraph, then ignore the indentation
58 // level of the first line
59 let ignore_previous_indents
=
60 saw_first_line
&& !saw_second_line
&& !line
.chars().all(|c
| c
.is_whitespace());
62 let min_indent
= if ignore_previous_indents { usize::MAX }
else { min_indent }
;
65 saw_second_line
= true;
68 if line
.chars().all(|c
| c
.is_whitespace()) {
71 saw_first_line
= true;
72 let mut whitespace
= 0;
73 line
.chars().all(|char| {
74 // Compare against either space or tab, ignoring whether they
76 if char == ' '
|| char == '
\t'
{
83 cmp
::min(min_indent
, whitespace
)
87 if !lines
.is_empty() {
88 let mut unindented
= vec
![lines
[0].trim_start().to_string()];
89 unindented
.extend_from_slice(
93 if line
.chars().all(|c
| c
.is_whitespace()) {
96 assert
!(line
.len() >= min_indent
);
97 line
[min_indent
..].to_string()
100 .collect
::<Vec
<_
>>(),
102 unindented
.join("\n")