Another refactoring in links.rs (#1001)
* Extract the concept of a link having a range or anchor specified So that other kinds of links can use this concept too. * Extract a function for parsing range or anchor
This commit is contained in:
parent
33d7e86fb6
commit
ce0c5f1d07
|
@ -102,11 +102,16 @@ where
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
enum LinkType<'a> {
|
enum LinkType<'a> {
|
||||||
Escaped,
|
Escaped,
|
||||||
IncludeRange(PathBuf, LineRange),
|
Include(PathBuf, RangeOrAnchor),
|
||||||
IncludeAnchor(PathBuf, String),
|
|
||||||
Playpen(PathBuf, Vec<&'a str>),
|
Playpen(PathBuf, Vec<&'a str>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
|
enum RangeOrAnchor {
|
||||||
|
Range(LineRange),
|
||||||
|
Anchor(String),
|
||||||
|
}
|
||||||
|
|
||||||
// A range of lines specified with some include directive.
|
// A range of lines specified with some include directive.
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
enum LineRange {
|
enum LineRange {
|
||||||
|
@ -165,8 +170,7 @@ impl<'a> LinkType<'a> {
|
||||||
let base = base.as_ref();
|
let base = base.as_ref();
|
||||||
match self {
|
match self {
|
||||||
LinkType::Escaped => None,
|
LinkType::Escaped => None,
|
||||||
LinkType::IncludeRange(p, _) => Some(return_relative_path(base, &p)),
|
LinkType::Include(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)),
|
LinkType::Playpen(p, _) => Some(return_relative_path(base, &p)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,9 +183,8 @@ fn return_relative_path<P: AsRef<Path>>(base: P, relative: P) -> PathBuf {
|
||||||
.to_path_buf()
|
.to_path_buf()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_include_path(path: &str) -> LinkType<'static> {
|
fn parse_range_or_anchor(parts: Option<&str>) -> RangeOrAnchor {
|
||||||
let mut parts = path.splitn(4, ':').fuse();
|
let mut parts = parts.unwrap_or("").splitn(3, ':').fuse();
|
||||||
let path = parts.next().unwrap().into();
|
|
||||||
|
|
||||||
let next_element = parts.next();
|
let next_element = parts.next();
|
||||||
let start = if let Some(value) = next_element.and_then(|s| s.parse::<usize>().ok()) {
|
let start = if let Some(value) = next_element.and_then(|s| s.parse::<usize>().ok()) {
|
||||||
|
@ -190,7 +193,7 @@ fn parse_include_path(path: &str) -> LinkType<'static> {
|
||||||
} else if let Some("") = next_element {
|
} else if let Some("") = next_element {
|
||||||
None
|
None
|
||||||
} else if let Some(anchor) = next_element {
|
} else if let Some(anchor) = next_element {
|
||||||
return LinkType::IncludeAnchor(path, String::from(anchor));
|
return RangeOrAnchor::Anchor(String::from(anchor));
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -202,14 +205,21 @@ fn parse_include_path(path: &str) -> LinkType<'static> {
|
||||||
let end = end.map(|s| s.parse::<usize>());
|
let end = end.map(|s| s.parse::<usize>());
|
||||||
|
|
||||||
match (start, end) {
|
match (start, end) {
|
||||||
(Some(start), Some(Ok(end))) => LinkType::IncludeRange(path, LineRange::from(start..end)),
|
(Some(start), Some(Ok(end))) => RangeOrAnchor::Range(LineRange::from(start..end)),
|
||||||
(Some(start), Some(Err(_))) => LinkType::IncludeRange(path, LineRange::from(start..)),
|
(Some(start), Some(Err(_))) => RangeOrAnchor::Range(LineRange::from(start..)),
|
||||||
(Some(start), None) => LinkType::IncludeRange(path, LineRange::from(start..start + 1)),
|
(Some(start), None) => RangeOrAnchor::Range(LineRange::from(start..start + 1)),
|
||||||
(None, Some(Ok(end))) => LinkType::IncludeRange(path, LineRange::from(..end)),
|
(None, Some(Ok(end))) => RangeOrAnchor::Range(LineRange::from(..end)),
|
||||||
(None, None) | (None, Some(Err(_))) => {
|
(None, None) | (None, Some(Err(_))) => RangeOrAnchor::Range(LineRange::from(RangeFull)),
|
||||||
LinkType::IncludeRange(path, LineRange::from(RangeFull))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_include_path(path: &str) -> LinkType<'static> {
|
||||||
|
let mut parts = path.splitn(2, ':');
|
||||||
|
|
||||||
|
let path = parts.next().unwrap().into();
|
||||||
|
let range_or_anchor = parse_range_or_anchor(parts.next());
|
||||||
|
|
||||||
|
LinkType::Include(path, range_or_anchor)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
|
@ -255,24 +265,14 @@ impl<'a> Link<'a> {
|
||||||
match self.link_type {
|
match self.link_type {
|
||||||
// omit the escape char
|
// omit the escape char
|
||||||
LinkType::Escaped => Ok((&self.link_text[1..]).to_owned()),
|
LinkType::Escaped => Ok((&self.link_text[1..]).to_owned()),
|
||||||
LinkType::IncludeRange(ref pat, ref range) => {
|
LinkType::Include(ref pat, ref range_or_anchor) => {
|
||||||
let target = base.join(pat);
|
let target = base.join(pat);
|
||||||
|
|
||||||
fs::read_to_string(&target)
|
fs::read_to_string(&target)
|
||||||
.map(|s| take_lines(&s, range.clone()))
|
.map(|s| match range_or_anchor {
|
||||||
.chain_err(|| {
|
RangeOrAnchor::Range(range) => take_lines(&s, range.clone()),
|
||||||
format!(
|
RangeOrAnchor::Anchor(anchor) => take_anchored_lines(&s, anchor),
|
||||||
"Could not read file for link {} ({})",
|
|
||||||
self.link_text,
|
|
||||||
target.display(),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
|
||||||
LinkType::IncludeAnchor(ref pat, ref anchor) => {
|
|
||||||
let target = base.join(pat);
|
|
||||||
|
|
||||||
fs::read_to_string(&target)
|
|
||||||
.map(|s| take_anchored_lines(&s, anchor))
|
|
||||||
.chain_err(|| {
|
.chain_err(|| {
|
||||||
format!(
|
format!(
|
||||||
"Could not read file for link {} ({})",
|
"Could not read file for link {} ({})",
|
||||||
|
@ -419,7 +419,10 @@ mod tests {
|
||||||
vec![Link {
|
vec![Link {
|
||||||
start_index: 22,
|
start_index: 22,
|
||||||
end_index: 48,
|
end_index: 48,
|
||||||
link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), LineRange::from(9..20)),
|
link_type: LinkType::Include(
|
||||||
|
PathBuf::from("file.rs"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(9..20))
|
||||||
|
),
|
||||||
link_text: "{{#include file.rs:10:20}}",
|
link_text: "{{#include file.rs:10:20}}",
|
||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
|
@ -435,7 +438,10 @@ mod tests {
|
||||||
vec![Link {
|
vec![Link {
|
||||||
start_index: 22,
|
start_index: 22,
|
||||||
end_index: 45,
|
end_index: 45,
|
||||||
link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), LineRange::from(9..10)),
|
link_type: LinkType::Include(
|
||||||
|
PathBuf::from("file.rs"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(9..10))
|
||||||
|
),
|
||||||
link_text: "{{#include file.rs:10}}",
|
link_text: "{{#include file.rs:10}}",
|
||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
|
@ -451,7 +457,10 @@ mod tests {
|
||||||
vec![Link {
|
vec![Link {
|
||||||
start_index: 22,
|
start_index: 22,
|
||||||
end_index: 46,
|
end_index: 46,
|
||||||
link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), LineRange::from(9..)),
|
link_type: LinkType::Include(
|
||||||
|
PathBuf::from("file.rs"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(9..))
|
||||||
|
),
|
||||||
link_text: "{{#include file.rs:10:}}",
|
link_text: "{{#include file.rs:10:}}",
|
||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
|
@ -467,7 +476,10 @@ mod tests {
|
||||||
vec![Link {
|
vec![Link {
|
||||||
start_index: 22,
|
start_index: 22,
|
||||||
end_index: 46,
|
end_index: 46,
|
||||||
link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), LineRange::from(..20)),
|
link_type: LinkType::Include(
|
||||||
|
PathBuf::from("file.rs"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(..20))
|
||||||
|
),
|
||||||
link_text: "{{#include file.rs::20}}",
|
link_text: "{{#include file.rs::20}}",
|
||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
|
@ -483,7 +495,10 @@ mod tests {
|
||||||
vec![Link {
|
vec![Link {
|
||||||
start_index: 22,
|
start_index: 22,
|
||||||
end_index: 44,
|
end_index: 44,
|
||||||
link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), LineRange::from(..)),
|
link_type: LinkType::Include(
|
||||||
|
PathBuf::from("file.rs"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(..))
|
||||||
|
),
|
||||||
link_text: "{{#include file.rs::}}",
|
link_text: "{{#include file.rs::}}",
|
||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
|
@ -499,7 +514,10 @@ mod tests {
|
||||||
vec![Link {
|
vec![Link {
|
||||||
start_index: 22,
|
start_index: 22,
|
||||||
end_index: 42,
|
end_index: 42,
|
||||||
link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), LineRange::from(..)),
|
link_type: LinkType::Include(
|
||||||
|
PathBuf::from("file.rs"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(..))
|
||||||
|
),
|
||||||
link_text: "{{#include file.rs}}",
|
link_text: "{{#include file.rs}}",
|
||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
|
@ -515,9 +533,9 @@ mod tests {
|
||||||
vec![Link {
|
vec![Link {
|
||||||
start_index: 22,
|
start_index: 22,
|
||||||
end_index: 49,
|
end_index: 49,
|
||||||
link_type: LinkType::IncludeAnchor(
|
link_type: LinkType::Include(
|
||||||
PathBuf::from("file.rs"),
|
PathBuf::from("file.rs"),
|
||||||
String::from("anchor")
|
RangeOrAnchor::Anchor(String::from("anchor"))
|
||||||
),
|
),
|
||||||
link_text: "{{#include file.rs:anchor}}",
|
link_text: "{{#include file.rs:anchor}}",
|
||||||
}]
|
}]
|
||||||
|
@ -585,7 +603,10 @@ mod tests {
|
||||||
Link {
|
Link {
|
||||||
start_index: 38,
|
start_index: 38,
|
||||||
end_index: 58,
|
end_index: 58,
|
||||||
link_type: LinkType::IncludeRange(PathBuf::from("file.rs"), LineRange::from(..)),
|
link_type: LinkType::Include(
|
||||||
|
PathBuf::from("file.rs"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(..))
|
||||||
|
),
|
||||||
link_text: "{{#include file.rs}}",
|
link_text: "{{#include file.rs}}",
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -617,7 +638,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary");
|
let link_type = parse_include_path("arbitrary");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeRange(PathBuf::from("arbitrary"), LineRange::from(RangeFull))
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(RangeFull))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,7 +650,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary:");
|
let link_type = parse_include_path("arbitrary:");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeRange(PathBuf::from("arbitrary"), LineRange::from(RangeFull))
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(RangeFull))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -635,7 +662,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary::");
|
let link_type = parse_include_path("arbitrary::");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeRange(PathBuf::from("arbitrary"), LineRange::from(RangeFull))
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(RangeFull))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,7 +674,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary::NaN");
|
let link_type = parse_include_path("arbitrary::NaN");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeRange(PathBuf::from("arbitrary"), LineRange::from(RangeFull))
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(RangeFull))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -653,7 +686,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary:5");
|
let link_type = parse_include_path("arbitrary:5");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeRange(PathBuf::from("arbitrary"), LineRange::from(4..5))
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(4..5))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,7 +698,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary:1");
|
let link_type = parse_include_path("arbitrary:1");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeRange(PathBuf::from("arbitrary"), LineRange::from(0..1))
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(0..1))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -671,7 +710,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary:0");
|
let link_type = parse_include_path("arbitrary:0");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeRange(PathBuf::from("arbitrary"), LineRange::from(0..1))
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(0..1))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -680,7 +722,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary:5:");
|
let link_type = parse_include_path("arbitrary:5:");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeRange(PathBuf::from("arbitrary"), LineRange::from(4..))
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(4..))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,7 +734,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary:5:NaN");
|
let link_type = parse_include_path("arbitrary:5:NaN");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeRange(PathBuf::from("arbitrary"), LineRange::from(4..))
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(4..))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,7 +746,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary::5");
|
let link_type = parse_include_path("arbitrary::5");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeRange(PathBuf::from("arbitrary"), LineRange::from(..5))
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(..5))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,7 +758,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary:5:10");
|
let link_type = parse_include_path("arbitrary:5:10");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeRange(PathBuf::from("arbitrary"), LineRange::from(4..10))
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(4..10))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,7 +770,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary:-5");
|
let link_type = parse_include_path("arbitrary:-5");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeAnchor(PathBuf::from("arbitrary"), "-5".to_string())
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Anchor("-5".to_string())
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,7 +782,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary:-5.7");
|
let link_type = parse_include_path("arbitrary:-5.7");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeAnchor(PathBuf::from("arbitrary"), "-5.7".to_string())
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Anchor("-5.7".to_string())
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,7 +794,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary:some-anchor:this-gets-ignored");
|
let link_type = parse_include_path("arbitrary:some-anchor:this-gets-ignored");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeAnchor(PathBuf::from("arbitrary"), "some-anchor".to_string())
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Anchor("some-anchor".to_string())
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -743,7 +806,10 @@ mod tests {
|
||||||
let link_type = parse_include_path("arbitrary:5:10:17:anything:");
|
let link_type = parse_include_path("arbitrary:5:10:17:anything:");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
link_type,
|
link_type,
|
||||||
LinkType::IncludeRange(PathBuf::from("arbitrary"), LineRange::from(4..10))
|
LinkType::Include(
|
||||||
|
PathBuf::from("arbitrary"),
|
||||||
|
RangeOrAnchor::Range(LineRange::from(4..10))
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue