Created
August 16, 2015 20:17
-
-
Save marcusklaas/1ce0906ec080ff8ece70 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub struct ListItems<'a, I, F1, F2, F3> | |
where I: Iterator | |
{ | |
codemap: &'a CodeMap, | |
inner: Peekable<I>, | |
get_lo: F1, | |
get_hi: F2, | |
get_item_string: F3, | |
prev_span_end: BytePos, | |
next_span_start: BytePos, | |
terminator: &'a str, | |
} | |
impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> | |
where I: Iterator<Item = &'a T>, | |
F1: Fn(&T) -> BytePos, | |
F2: Fn(&T) -> BytePos, | |
F3: Fn(&T) -> String | |
{ | |
type Item = ListItem; | |
fn next(&mut self) -> Option<Self::Item> { | |
let white_space: &[_] = &[' ', '\t']; | |
self.inner.next().map(|item| { | |
// Pre-comment | |
let pre_snippet = self.codemap.span_to_snippet(codemap::mk_sp(self.prev_span_end, | |
(self.get_lo)(item))) | |
.unwrap(); | |
let pre_snippet = pre_snippet.trim(); | |
let pre_comment = if pre_snippet.len() > 0 { | |
Some(pre_snippet.to_owned()) | |
} else { | |
None | |
}; | |
// Post-comment | |
let next_start = match self.inner.peek() { | |
Some(ref next_item) => (self.get_lo)(next_item), | |
None => self.next_span_start | |
}; | |
let post_snippet = self.codemap.span_to_snippet(codemap::mk_sp((self.get_hi)(item), | |
next_start)) | |
.unwrap(); | |
let comment_end = match self.inner.peek() { | |
Some(..) => { | |
let block_open_index = post_snippet.find("/*"); | |
let newline_index = post_snippet.find('\n'); | |
let separator_index = post_snippet.find_uncommented(",").unwrap(); | |
match (block_open_index, newline_index) { | |
// Separator before comment, with the next item on same line. | |
// Comment belongs to next item. | |
(Some(i), None) if i > separator_index => { | |
separator_index + 1 | |
} | |
// Block-style post-comment before the separator. | |
(Some(i), None) => { | |
cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, | |
separator_index + 1) | |
} | |
// Block-style post-comment. Either before or after the separator. | |
(Some(i), Some(j)) if i < j => { | |
cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, | |
separator_index + 1) | |
} | |
// Potential *single* line comment. | |
(_, Some(j)) => { j + 1 } | |
_ => post_snippet.len() | |
} | |
}, | |
None => { | |
post_snippet.find_uncommented(self.terminator) | |
.unwrap_or(post_snippet.len()) | |
} | |
}; | |
// Cleanup post-comment: strip separators and whitespace. | |
self.prev_span_end = (self.get_hi)(item) + BytePos(comment_end as u32); | |
let mut post_snippet = post_snippet[..comment_end].trim(); | |
if post_snippet.starts_with(',') { | |
post_snippet = post_snippet[1..].trim_matches(white_space); | |
} else if post_snippet.ends_with(",") { | |
post_snippet = post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space); | |
} | |
let post_comment = if post_snippet.len() > 0 { | |
Some(post_snippet.to_owned()) | |
} else { | |
None | |
}; | |
ListItem { | |
pre_comment: pre_comment, | |
item: (self.get_item_string)(item), | |
post_comment: post_comment, | |
} | |
}) | |
} | |
} | |
pub fn itemize_list<'a, 'b, T, I, F1, F2, F3>(codemap: &'a CodeMap, | |
inner: I, | |
terminator: &'a str, | |
get_lo: F1, | |
get_hi: F2, | |
get_item_string: F3, | |
prev_span_end: BytePos, | |
next_span_start: BytePos) | |
-> ListItems<'a, I, F1, F2, F3> | |
where T: 'b, | |
I: Iterator<Item = &'b T>, | |
F1: Fn(&T) -> BytePos, | |
F2: Fn(&T) -> BytePos, | |
F3: Fn(&T) -> String | |
{ | |
ListItems { | |
codemap: codemap, | |
inner: inner.peekable(), | |
get_lo: get_lo, | |
get_hi: get_hi, | |
get_item_string: get_item_string, | |
prev_span_end: prev_span_end, | |
next_span_start: next_span_start, | |
terminator: terminator, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment