use seal::pair::{AlignmentSet, MemoryMappedAlignmentMatrix, SmithWaterman, Step}; // (line pos, line pos) pub fn match_lines(code: &str, start: &str, end: &str) -> Option<(usize, usize)> { let code_chars: Vec = code.chars().collect(); if code_chars.is_empty() || start.is_empty() || end.is_empty() { return None; } let strategy = SmithWaterman::new(3, -1, -1, -1); if start.ends_with(end) { let pattern_chars: Vec = start.chars().collect(); let set: AlignmentSet = AlignmentSet::new(code_chars.len(), pattern_chars.len(), strategy, |x, y| { code_chars[x] == pattern_chars[y] }) .ok()?; let alignment = set.local_alignment(); let mut start_char_pos = None; let mut end_char_pos = None; for step in alignment.steps() { if let Step::Align { x, .. } = step { if start_char_pos.is_none() { start_char_pos = Some(x); } end_char_pos = Some(x); } } let start_char = start_char_pos?; let end_char = end_char_pos?; let start_line = code[..start_char].lines().count().saturating_sub(1); let end_line = code[..=end_char].lines().count().saturating_sub(1); Some((start_line, end_line)) } else { let start_chars: Vec = start.chars().collect(); let start_set: AlignmentSet = AlignmentSet::new( code_chars.len(), start_chars.len(), strategy.clone(), |x, y| code_chars[x] == start_chars[y], ) .ok()?; let start_alignment = start_set.local_alignment(); let start_char_pos = start_alignment .steps() .filter_map(|step| { if let Step::Align { x, .. } = step { Some(x) } else { None } }) .next()?; let end_chars: Vec = end.chars().collect(); let remaining_code: Vec = code_chars[start_char_pos..].to_vec(); let end_set: AlignmentSet = AlignmentSet::new(remaining_code.len(), end_chars.len(), strategy, |x, y| { remaining_code[x] == end_chars[y] }) .ok()?; let end_char_pos_relative = end_set .local_alignments() .filter_map(|end_alignment| { end_alignment .steps() .filter_map(|step| { if let Step::Align { x, .. } = step { Some(x) } else { None } }) .last() }) .min()?; let end_char_pos = start_char_pos + end_char_pos_relative; let start_line = code[..=start_char_pos].lines().count().saturating_sub(1); let end_line = code[..=end_char_pos].lines().count().saturating_sub(1); Some((start_line, end_line)) } } // (char pos, char pos) pub fn match_content(code: &str, pattern: &str) -> Vec<(usize, usize)> { let code_chars: Vec = code.chars().collect(); if code_chars.is_empty() || pattern.is_empty() { return vec![]; } let strategy = SmithWaterman::new(3, -1, -1, -1); let pattern_chars: Vec = pattern.chars().collect(); let set: AlignmentSet = match AlignmentSet::new(code_chars.len(), pattern_chars.len(), strategy, |x, y| { code_chars[x] == pattern_chars[y] }) { Ok(set) => set, Err(_) => return vec![], }; set.local_alignments() .filter_map(|alignment| { let mut start_char_pos = None; let mut end_char_pos = None; for step in alignment.steps() { if let Step::Align { x, .. } = step { if start_char_pos.is_none() { start_char_pos = Some(x); } end_char_pos = Some(x); } } match (start_char_pos, end_char_pos) { (Some(start), Some(end)) => Some((start, end)), _ => None, } }) .collect() }