|
|
@ -154,6 +154,12 @@ fn find_nth_closest_pairs_plain(
|
|
|
|
Err(Error::PairNotFound)
|
|
|
|
Err(Error::PairNotFound)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub enum FindType {
|
|
|
|
|
|
|
|
Surround(usize),
|
|
|
|
|
|
|
|
Next(usize),
|
|
|
|
|
|
|
|
Prev(usize),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Find the position of surround pairs of `ch` which can be either a closing
|
|
|
|
/// Find the position of surround pairs of `ch` which can be either a closing
|
|
|
|
/// or opening pair. `n` will skip n - 1 pairs (eg. n=2 will discard (only)
|
|
|
|
/// or opening pair. `n` will skip n - 1 pairs (eg. n=2 will discard (only)
|
|
|
|
/// the first pair found and keep looking)
|
|
|
|
/// the first pair found and keep looking)
|
|
|
@ -161,7 +167,7 @@ pub fn find_nth_pairs_pos(
|
|
|
|
text: RopeSlice,
|
|
|
|
text: RopeSlice,
|
|
|
|
ch: char,
|
|
|
|
ch: char,
|
|
|
|
range: Range,
|
|
|
|
range: Range,
|
|
|
|
n: usize,
|
|
|
|
find_type: FindType,
|
|
|
|
) -> Result<(usize, usize)> {
|
|
|
|
) -> Result<(usize, usize)> {
|
|
|
|
if text.len_chars() < 2 {
|
|
|
|
if text.len_chars() < 2 {
|
|
|
|
return Err(Error::PairNotFound);
|
|
|
|
return Err(Error::PairNotFound);
|
|
|
@ -172,6 +178,17 @@ pub fn find_nth_pairs_pos(
|
|
|
|
|
|
|
|
|
|
|
|
let (open, close) = get_pair(ch);
|
|
|
|
let (open, close) = get_pair(ch);
|
|
|
|
let pos = range.cursor(text);
|
|
|
|
let pos = range.cursor(text);
|
|
|
|
|
|
|
|
let (pos, n) = match find_type {
|
|
|
|
|
|
|
|
FindType::Surround(n) => (pos, n),
|
|
|
|
|
|
|
|
FindType::Next(n) => match search::find_nth_next(text, open, pos, n) {
|
|
|
|
|
|
|
|
Some(next_pos) => (next_pos + 1, 1),
|
|
|
|
|
|
|
|
None => return Err(Error::PairNotFound),
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
FindType::Prev(n) => match search::find_nth_prev(text, close, pos, n) {
|
|
|
|
|
|
|
|
Some(next_pos) => (next_pos - 1, 1),
|
|
|
|
|
|
|
|
None => return Err(Error::PairNotFound),
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let (open, close) = if open == close {
|
|
|
|
let (open, close) = if open == close {
|
|
|
|
if Some(open) == text.get_char(pos) {
|
|
|
|
if Some(open) == text.get_char(pos) {
|
|
|
@ -298,7 +315,7 @@ pub fn get_surround_pos(
|
|
|
|
for &range in selection {
|
|
|
|
for &range in selection {
|
|
|
|
let (open_pos, close_pos) = {
|
|
|
|
let (open_pos, close_pos) = {
|
|
|
|
let range_raw = match ch {
|
|
|
|
let range_raw = match ch {
|
|
|
|
Some(ch) => find_nth_pairs_pos(text, ch, range, skip)?,
|
|
|
|
Some(ch) => find_nth_pairs_pos(text, ch, range, FindType::Surround(skip))?,
|
|
|
|
None => find_nth_closest_pairs_pos(syntax, text, range, skip)?,
|
|
|
|
None => find_nth_closest_pairs_pos(syntax, text, range, skip)?,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
let range = Range::new(range_raw.0, range_raw.1);
|
|
|
|
let range = Range::new(range_raw.0, range_raw.1);
|
|
|
@ -392,8 +409,13 @@ mod test {
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(2, expectations.len());
|
|
|
|
assert_eq!(2, expectations.len());
|
|
|
|
assert_eq!(
|
|
|
|
assert_eq!(
|
|
|
|
find_nth_pairs_pos(doc.slice(..), '\'', selection.primary(), 1)
|
|
|
|
find_nth_pairs_pos(
|
|
|
|
.expect("find should succeed"),
|
|
|
|
doc.slice(..),
|
|
|
|
|
|
|
|
'\'',
|
|
|
|
|
|
|
|
selection.primary(),
|
|
|
|
|
|
|
|
FindType::Surround(1)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.expect("find should succeed"),
|
|
|
|
(expectations[0], expectations[1])
|
|
|
|
(expectations[0], expectations[1])
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -409,7 +431,46 @@ mod test {
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(2, expectations.len());
|
|
|
|
assert_eq!(2, expectations.len());
|
|
|
|
assert_eq!(
|
|
|
|
assert_eq!(
|
|
|
|
find_nth_pairs_pos(doc.slice(..), '\'', selection.primary(), 2)
|
|
|
|
find_nth_pairs_pos(
|
|
|
|
|
|
|
|
doc.slice(..),
|
|
|
|
|
|
|
|
'\'',
|
|
|
|
|
|
|
|
selection.primary(),
|
|
|
|
|
|
|
|
FindType::Surround(2)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.expect("find should succeed"),
|
|
|
|
|
|
|
|
(expectations[0], expectations[1])
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
|
|
fn test_find_inside_third_next_quote() {
|
|
|
|
|
|
|
|
#[rustfmt::skip]
|
|
|
|
|
|
|
|
let (doc, selection, expectations) =
|
|
|
|
|
|
|
|
rope_with_selections_and_expectations(
|
|
|
|
|
|
|
|
"some 'nested 'quoted' text' on this 'line'\n'and this one'",
|
|
|
|
|
|
|
|
" ^ _ _ \n "
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(2, expectations.len());
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
|
|
find_nth_pairs_pos(doc.slice(..), '\'', selection.primary(), FindType::Next(3))
|
|
|
|
|
|
|
|
.expect("find should succeed"),
|
|
|
|
|
|
|
|
(expectations[0], expectations[1])
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
|
|
fn test_find_inside_prev_quote() {
|
|
|
|
|
|
|
|
#[rustfmt::skip]
|
|
|
|
|
|
|
|
let (doc, selection, expectations) =
|
|
|
|
|
|
|
|
rope_with_selections_and_expectations(
|
|
|
|
|
|
|
|
"some 'nested 'quoted' text' on this 'line'\n'and this one'",
|
|
|
|
|
|
|
|
" _ _ ^ \n "
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(2, expectations.len());
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
|
|
find_nth_pairs_pos(doc.slice(..), '\'', selection.primary(), FindType::Prev(1))
|
|
|
|
.expect("find should succeed"),
|
|
|
|
.expect("find should succeed"),
|
|
|
|
(expectations[0], expectations[1])
|
|
|
|
(expectations[0], expectations[1])
|
|
|
|
)
|
|
|
|
)
|
|
|
@ -425,7 +486,12 @@ mod test {
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
assert_eq!(
|
|
|
|
find_nth_pairs_pos(doc.slice(..), '\'', selection.primary(), 1),
|
|
|
|
find_nth_pairs_pos(
|
|
|
|
|
|
|
|
doc.slice(..),
|
|
|
|
|
|
|
|
'\'',
|
|
|
|
|
|
|
|
selection.primary(),
|
|
|
|
|
|
|
|
FindType::Surround(1)
|
|
|
|
|
|
|
|
),
|
|
|
|
Err(Error::CursorOnAmbiguousPair)
|
|
|
|
Err(Error::CursorOnAmbiguousPair)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|