Factor out the use of different ranges from linktype
This eliminates some duplication and will enable different kinds of LinkTypes to have line number ranges. Implement `From` for the std `Range` types to enable easier construction. The new code reaaalllly makes me wish for a delegation mechanism though :(
This commit is contained in:
parent
0f56c09d3a
commit
07459aef60
|
@ -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<usize>),
|
||||
IncludeRangeFrom(PathBuf, RangeFrom<usize>),
|
||||
IncludeRangeTo(PathBuf, RangeTo<usize>),
|
||||
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<usize>),
|
||||
RangeFrom(RangeFrom<usize>),
|
||||
RangeTo(RangeTo<usize>),
|
||||
RangeFull(RangeFull),
|
||||
}
|
||||
|
||||
impl RangeBounds<usize> 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<Range<usize>> for LineRange {
|
||||
fn from(r: Range<usize>) -> LineRange {
|
||||
LineRange::Range(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RangeFrom<usize>> for LineRange {
|
||||
fn from(r: RangeFrom<usize>) -> LineRange {
|
||||
LineRange::RangeFrom(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RangeTo<usize>> for LineRange {
|
||||
fn from(r: RangeTo<usize>) -> LineRange {
|
||||
LineRange::RangeTo(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RangeFull> for LineRange {
|
||||
fn from(r: RangeFull) -> LineRange {
|
||||
LineRange::RangeFull(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> LinkType<'a> {
|
||||
fn relative_path<P: AsRef<Path>>(self, base: P) -> Option<PathBuf> {
|
||||
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::<usize>().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}}",
|
||||
}
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue