diff --git a/src/preprocess/links.rs b/src/preprocess/links.rs index 2a469cde..08d36dcd 100644 --- a/src/preprocess/links.rs +++ b/src/preprocess/links.rs @@ -2,7 +2,7 @@ use crate::errors::*; use crate::utils::{take_anchored_lines, take_lines}; use regex::{CaptureMatches, Captures, Regex}; use std::fs; -use std::ops::{Range, RangeFrom, RangeFull, RangeTo}; +use std::ops::{Bound, Range, RangeBounds, RangeFrom, RangeFull, RangeTo}; use std::path::{Path, PathBuf}; use super::{Preprocessor, PreprocessorContext}; @@ -102,23 +102,70 @@ where #[derive(PartialEq, Debug, Clone)] enum LinkType<'a> { Escaped, - IncludeRange(PathBuf, Range), - IncludeRangeFrom(PathBuf, RangeFrom), - IncludeRangeTo(PathBuf, RangeTo), - IncludeRangeFull(PathBuf, RangeFull), + IncludeRange(PathBuf, LineRange), IncludeAnchor(PathBuf, String), Playpen(PathBuf, Vec<&'a str>), } +// A range of lines specified with some include directive. +#[derive(PartialEq, Debug, Clone)] +enum LineRange { + Range(Range), + RangeFrom(RangeFrom), + RangeTo(RangeTo), + RangeFull(RangeFull), +} + +impl RangeBounds for LineRange { + fn start_bound(&self) -> Bound<&usize> { + match self { + LineRange::Range(r) => r.start_bound(), + LineRange::RangeFrom(r) => r.start_bound(), + LineRange::RangeTo(r) => r.start_bound(), + LineRange::RangeFull(r) => r.start_bound(), + } + } + + fn end_bound(&self) -> Bound<&usize> { + match self { + LineRange::Range(r) => r.end_bound(), + LineRange::RangeFrom(r) => r.end_bound(), + LineRange::RangeTo(r) => r.end_bound(), + LineRange::RangeFull(r) => r.end_bound(), + } + } +} + +impl From> for LineRange { + fn from(r: Range) -> LineRange { + LineRange::Range(r) + } +} + +impl From> for LineRange { + fn from(r: RangeFrom) -> LineRange { + LineRange::RangeFrom(r) + } +} + +impl From> for LineRange { + fn from(r: RangeTo) -> LineRange { + LineRange::RangeTo(r) + } +} + +impl From for LineRange { + fn from(r: RangeFull) -> LineRange { + LineRange::RangeFull(r) + } +} + impl<'a> LinkType<'a> { fn relative_path>(self, base: P) -> Option { let base = base.as_ref(); match self { LinkType::Escaped => None, LinkType::IncludeRange(p, _) => Some(return_relative_path(base, &p)), - LinkType::IncludeRangeFrom(p, _) => Some(return_relative_path(base, &p)), - LinkType::IncludeRangeTo(p, _) => Some(return_relative_path(base, &p)), - LinkType::IncludeRangeFull(p, _) => Some(return_relative_path(base, &p)), LinkType::IncludeAnchor(p, _) => Some(return_relative_path(base, &p)), LinkType::Playpen(p, _) => Some(return_relative_path(base, &p)), } @@ -155,24 +202,21 @@ fn parse_include_path(path: &str) -> LinkType<'static> { let end = end.and_then(|s| s.parse::().ok()); match start { Some(start) => match end { - Some(end) => LinkType::IncludeRange(path, Range { start, end }), + Some(end) => LinkType::IncludeRange(path, LineRange::from(start..end)), None => { if has_end { - LinkType::IncludeRangeFrom(path, RangeFrom { start }) + LinkType::IncludeRange(path, LineRange::from(start..)) } else { LinkType::IncludeRange( path, - Range { - start, - end: start + 1, - }, + LineRange::from(start..start + 1), ) } } }, None => match end { - Some(end) => LinkType::IncludeRangeTo(path, RangeTo { end }), - None => LinkType::IncludeRangeFull(path, RangeFull), + Some(end) => LinkType::IncludeRange(path, LineRange::from(..end)), + None => LinkType::IncludeRange(path, LineRange::from(RangeFull)), }, } } @@ -233,43 +277,6 @@ impl<'a> Link<'a> { ) }) } - LinkType::IncludeRangeFrom(ref pat, ref range) => { - let target = base.join(pat); - - fs::read_to_string(&target) - .map(|s| take_lines(&s, range.clone())) - .chain_err(|| { - format!( - "Could not read file for link {} ({})", - self.link_text, - target.display(), - ) - }) - } - LinkType::IncludeRangeTo(ref pat, ref range) => { - let target = base.join(pat); - - fs::read_to_string(&target) - .map(|s| take_lines(&s, *range)) - .chain_err(|| { - format!( - "Could not read file for link {} ({})", - self.link_text, - target.display(), - ) - }) - } - LinkType::IncludeRangeFull(ref pat, _) => { - let target = base.join(pat); - - fs::read_to_string(&target).chain_err(|| { - format!( - "Could not read file for link {} ({})", - self.link_text, - target.display() - ) - }) - } LinkType::IncludeAnchor(ref pat, ref anchor) => { let target = base.join(pat); @@ -421,7 +428,7 @@ mod tests { vec![Link { start_index: 22, end_index: 48, - link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), 9..20), + link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), LineRange::from(9..20)), link_text: "{{#include file.rs:10:20}}", }] ); @@ -437,7 +444,7 @@ mod tests { vec![Link { start_index: 22, end_index: 45, - link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), 9..10), + link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), LineRange::from(9..10)), link_text: "{{#include file.rs:10}}", }] ); @@ -453,7 +460,7 @@ mod tests { vec![Link { start_index: 22, end_index: 46, - link_type: LinkType::IncludeRangeFrom(PathBuf::from("file.rs"), 9..), + link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), LineRange::from(9..)), link_text: "{{#include file.rs:10:}}", }] ); @@ -469,7 +476,7 @@ mod tests { vec![Link { start_index: 22, end_index: 46, - link_type: LinkType::IncludeRangeTo(PathBuf::from("file.rs"), ..20), + link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), LineRange::from(..20)), link_text: "{{#include file.rs::20}}", }] ); @@ -485,7 +492,7 @@ mod tests { vec![Link { start_index: 22, end_index: 44, - link_type: LinkType::IncludeRangeFull(PathBuf::from("file.rs"), ..), + link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), LineRange::from(..)), link_text: "{{#include file.rs::}}", }] ); @@ -501,7 +508,7 @@ mod tests { vec![Link { start_index: 22, end_index: 42, - link_type: LinkType::IncludeRangeFull(PathBuf::from("file.rs"), ..), + link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), LineRange::from(..)), link_text: "{{#include file.rs}}", }] ); @@ -587,7 +594,7 @@ mod tests { Link { start_index: 38, end_index: 58, - link_type: LinkType::IncludeRangeFull(PathBuf::from("file.rs"), ..), + link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), LineRange::from(..)), link_text: "{{#include file.rs}}", } );