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 pass: 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),
49 fn unindent(s: &str) -> String {
50 let lines = s.lines().collect::<Vec<&str> >();
51 let mut saw_first_line = false;
52 let mut saw_second_line = false;
53 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 =
62 !line.chars().all(|c| c.is_whitespace());
64 let min_indent = if ignore_previous_indents {
71 saw_second_line = true;
74 if line.chars().all(|c| c.is_whitespace()) {
77 saw_first_line = true;
78 let mut whitespace = 0;
79 line.chars().all(|char| {
80 // Compare against either space or tab, ignoring whether they
82 if char == ' ' || char == '\t' {
89 cmp::min(min_indent, whitespace)
93 if !lines.is_empty() {
94 let mut unindented = vec![ lines[0].trim_start().to_string() ];
95 unindented.extend_from_slice(&lines[1..].iter().map(|&line| {
96 if line.chars().all(|c| c.is_whitespace()) {
99 assert!(line.len() >= min_indent);
100 line[min_indent..].to_string()
102 }).collect::<Vec<_>>());
103 unindented.join("\n")