From 4c50a25662358fc16f2c85b60e3f8b7a6ad124b2 Mon Sep 17 00:00:00 2001 From: Emir Salkic Date: Thu, 14 Jul 2022 15:07:06 +0200 Subject: [PATCH] add option -no-indent to remove indentation --- src/preprocess/links.rs | 27 ++++++++++++++++++++++++--- src/utils/mod.rs | 2 +- src/utils/string.rs | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/preprocess/links.rs b/src/preprocess/links.rs index 7ca6fd34..4ee2e5e9 100644 --- a/src/preprocess/links.rs +++ b/src/preprocess/links.rs @@ -1,6 +1,6 @@ use crate::errors::*; use crate::utils::{ - take_anchored_lines, take_lines, take_rustdoc_include_anchored_lines, + take_anchored_lines, take_lines, take_remove_indent, take_rustdoc_include_anchored_lines, take_rustdoc_include_lines, }; use regex::{CaptureMatches, Captures, Regex}; @@ -134,6 +134,7 @@ where enum LinkType<'a> { Escaped, Include(PathBuf, RangeOrAnchor), + IncludeNoIndent(PathBuf, RangeOrAnchor), Playground(PathBuf, Vec<&'a str>), RustdocInclude(PathBuf, RangeOrAnchor), Title(&'a str), @@ -205,6 +206,7 @@ impl<'a> LinkType<'a> { match self { LinkType::Escaped => None, LinkType::Include(p, _) => Some(return_relative_path(base, &p)), + LinkType::IncludeNoIndent(p, _) => Some(return_relative_path(base, &p)), LinkType::Playground(p, _) => Some(return_relative_path(base, &p)), LinkType::RustdocInclude(p, _) => Some(return_relative_path(base, &p)), LinkType::Title(_) => None, @@ -250,12 +252,15 @@ fn parse_range_or_anchor(parts: Option<&str>) -> RangeOrAnchor { } fn parse_include_path(path: &str) -> LinkType<'static> { - let mut parts = path.splitn(2, ':'); + let mut parts = path.splitn(3, ':'); let path = parts.next().unwrap().into(); let range_or_anchor = parse_range_or_anchor(parts.next()); - LinkType::Include(path, range_or_anchor) + match parts.next() { + Some(_some) => LinkType::IncludeNoIndent(path, range_or_anchor), + None => LinkType::Include(path, range_or_anchor), + } } fn parse_rustdoc_include_path(path: &str) -> LinkType<'static> { @@ -342,6 +347,22 @@ impl<'a> Link<'a> { ) }) } + LinkType::IncludeNoIndent(ref pat, ref range_or_anchor) => { + let target = base.join(pat); + let s = fs::read_to_string(&target) + .map(|s| match range_or_anchor { + RangeOrAnchor::Range(range) => take_lines(&s, range.clone()), + RangeOrAnchor::Anchor(anchor) => take_anchored_lines(&s, anchor), + }) + .with_context(|| { + format!( + "Could not read file for link {} ({})", + self.link_text, + target.display(), + ) + }); + take_remove_indent(s) + } LinkType::RustdocInclude(ref pat, ref range_or_anchor) => { let target = base.join(pat); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index a205633f..a5b06022 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -14,7 +14,7 @@ use std::fmt::Write; use std::path::Path; pub use self::string::{ - take_anchored_lines, take_lines, take_rustdoc_include_anchored_lines, + take_anchored_lines, take_lines, take_remove_indent, take_rustdoc_include_anchored_lines, take_rustdoc_include_lines, }; diff --git a/src/utils/string.rs b/src/utils/string.rs index 97485d7b..fef7987c 100644 --- a/src/utils/string.rs +++ b/src/utils/string.rs @@ -1,3 +1,4 @@ +use anyhow::Error; use regex::Regex; use std::ops::Bound::{Excluded, Included, Unbounded}; use std::ops::RangeBounds; @@ -114,6 +115,39 @@ pub fn take_rustdoc_include_anchored_lines(s: &str, anchor: &str) -> String { output } +pub fn take_remove_indent(s: Result) -> Result { + match s { + Err(_) => s, + Ok(_str) => Ok(take_format_remove_indent(_str.as_str())), + } +} + +fn take_format_remove_indent(str: &str) -> String { + let mut output = Vec::::new(); + let mut min_indent = usize::MAX; + + for line in str.lines() { + for (index, c) in line.chars().enumerate() { + if !c.is_whitespace() && min_indent > index { + min_indent = index; + break; + } + } + } + + for line in str.lines() { + let formatted: String = line + .chars() + .take(0) + .chain(line.chars().skip(min_indent)) + .collect(); + + output.push(formatted); + } + + output.join("\n") +} + #[cfg(test)] mod tests { use super::{