Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f4827c8
feat: support add support for helix files
nik-rev Jan 27, 2025
fa2de32
feat: implement basic highlighting (does not handle newlines yet)
nik-rev Jan 27, 2025
9e26253
feat: implement line breaks for custom helix renderer
nik-rev Jan 27, 2025
4a3bebc
fix: highlighted helix code block on windows
nik-rev Jan 27, 2025
01b8493
refactor: variable names
nik-rev Jan 27, 2025
443d2c8
docs: add informational comments
nik-rev Jan 27, 2025
6987b1d
feat: revert unnecessary changes
nik-rev Jan 27, 2025
51efd7e
chore: remove unnecessary files
nik-rev Jan 27, 2025
768a646
chore: remove unused imports
nik-rev Jan 27, 2025
5414377
Revert "feat: revert unnecessary changes"
nik-rev Jan 27, 2025
b51ca5d
Revert "chore: remove unnecessary files"
nik-rev Jan 27, 2025
ef5c878
style: revert formatting changes
nik-rev Jan 27, 2025
8f4d4c3
chore: remove example
nik-rev Jan 27, 2025
d16b27c
chore: remove unneeded file
nik-rev Jan 27, 2025
d7bb5e9
feat: use dummy values and not tree-sitter-helix
nik-rev Jan 27, 2025
83271b9
chore: remove pointless language
nik-rev Jan 28, 2025
7dd3061
fix: panic when couldn't parse selection string
nik-rev Jan 28, 2025
1501d0a
feat: print error to the user instead of panic
nik-rev Jan 28, 2025
a82e00d
test: handle error by unwrapping
nik-rev Jan 28, 2025
91ee5fd
fix: apply correct style to primary selection
nik-rev Jan 28, 2025
03d627a
chore: remove example
nik-rev Jan 28, 2025
3fed359
chore: improve error messages
nik-rev Jan 28, 2025
8eb0ac4
feat: rename file type to `.multicursor`
nik-rev Jan 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions helix-core/src/movement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2050,7 +2050,7 @@ mod test {
];

for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let (s, selection) = crate::test::parse_selection_string(before).unwrap();
let text = Rope::from(s.as_str());
let selection =
selection.transform(|r| move_prev_paragraph(text.slice(..), r, 1, Movement::Move));
Expand All @@ -2073,7 +2073,7 @@ mod test {
];

for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let (s, selection) = crate::test::parse_selection_string(before).unwrap();
let text = Rope::from(s.as_str());
let selection =
selection.transform(|r| move_prev_paragraph(text.slice(..), r, 2, Movement::Move));
Expand All @@ -2096,7 +2096,7 @@ mod test {
];

for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let (s, selection) = crate::test::parse_selection_string(before).unwrap();
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| move_prev_paragraph(text.slice(..), r, 1, Movement::Extend));
Expand Down Expand Up @@ -2138,7 +2138,7 @@ mod test {
];

for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let (s, selection) = crate::test::parse_selection_string(before).unwrap();
let text = Rope::from(s.as_str());
let selection =
selection.transform(|r| move_next_paragraph(text.slice(..), r, 1, Movement::Move));
Expand All @@ -2161,7 +2161,7 @@ mod test {
];

for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let (s, selection) = crate::test::parse_selection_string(before).unwrap();
let text = Rope::from(s.as_str());
let selection =
selection.transform(|r| move_next_paragraph(text.slice(..), r, 2, Movement::Move));
Expand All @@ -2184,7 +2184,7 @@ mod test {
];

for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let (s, selection) = crate::test::parse_selection_string(before).unwrap();
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| move_next_paragraph(text.slice(..), r, 1, Movement::Extend));
Expand Down
5 changes: 3 additions & 2 deletions helix-core/src/selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1202,7 +1202,7 @@ mod test {

#[test]
fn selection_line_ranges() {
let (text, selection) = crate::test::print(
let (text, selection) = crate::test::parse_selection_string(
r#" L0
#[|these]# line #(|ranges)# are #(|merged)# L1
L2
Expand All @@ -1218,7 +1218,8 @@ mod test {
adjacent #(|ranges)# L12
are merged #(|the same way)# L13
"#,
);
)
.unwrap();
let rope = Rope::from_str(&text);
assert_eq!(
vec![(1, 1), (3, 3), (5, 6), (8, 10), (12, 13)],
Expand Down
77 changes: 46 additions & 31 deletions helix-core/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ use smallvec::SmallVec;
use std::cmp::Reverse;
use unicode_segmentation::UnicodeSegmentation;

/// Convert annotated test string to test string and selection.
#[derive(Debug)]
pub enum ParseSelectionError {
MoreThanOnePrimary(String),
MissingClosingPair(String),
MissingPrimary(String),
}

/// Convert string annotated with selections to string and selection.
///
/// `#[|` for primary selection with head before anchor followed by `]#`.
/// `#(|` for secondary selection with head before anchor followed by `)#`.
Expand All @@ -19,21 +26,15 @@ use unicode_segmentation::UnicodeSegmentation;
/// # Examples
///
/// ```
/// use helix_core::{Range, Selection, test::print};
/// use helix_core::{Range, Selection, test::parse_selection_string};
/// use smallvec::smallvec;
///
/// assert_eq!(
/// print("#[a|]#b#(|c)#"),
/// parse_selection_string("#[a|]#b#(|c)#").unwrap(),
/// ("abc".to_owned(), Selection::new(smallvec![Range::new(0, 1), Range::new(3, 2)], 0))
/// );
/// ```
///
/// # Panics
///
/// Panics when missing primary or appeared more than once.
/// Panics when missing head or anchor.
/// Panics when head come after head or anchor come after anchor.
pub fn print(s: &str) -> (String, Selection) {
pub fn parse_selection_string(s: &str) -> Result<(String, Selection), ParseSelectionError> {
let mut primary_idx = None;
let mut ranges = SmallVec::new();
let mut iter = UnicodeSegmentation::graphemes(s, true).peekable();
Expand All @@ -59,7 +60,10 @@ pub fn print(s: &str) -> (String, Selection) {
};

if is_primary && primary_idx.is_some() {
panic!("primary `#[` already appeared {:?} {:?}", left, s);
return Err(ParseSelectionError::MoreThanOnePrimary(format!(
"Can only have 1 primary selection: {:?} {:?}",
left, s
)));
}

let head_at_beg = iter.next_if_eq(&"|").is_some();
Expand Down Expand Up @@ -116,19 +120,30 @@ pub fn print(s: &str) -> (String, Selection) {
}

if head_at_beg {
panic!("missing end `{}#` {:?} {:?}", close_pair, left, s);
return Err(ParseSelectionError::MissingClosingPair(format!(
"Missing end `{}#`: {:?} {:?}",
close_pair, left, s
)));
} else {
panic!("missing end `|{}#` {:?} {:?}", close_pair, left, s);
return Err(ParseSelectionError::MissingClosingPair(format!(
"Missing end `|{}#`: {:?} {:?}",
close_pair, left, s
)));
}
}

let primary = match primary_idx {
Some(i) => i,
None => panic!("missing primary `#[|]#` {:?}", s),
None => {
return Err(ParseSelectionError::MissingPrimary(format!(
"Missing primary `#[|]#:` {:?}",
s
)));
}
};

let selection = Selection::new(ranges, primary);
(left, selection)
Ok((left, selection))
}

/// Convert test string and selection to annotated test string.
Expand Down Expand Up @@ -187,27 +202,27 @@ mod test {
fn print_single() {
assert_eq!(
(String::from("hello"), Selection::single(1, 0)),
print("#[|h]#ello")
parse_selection_string("#[|h]#ello").unwrap()
);
assert_eq!(
(String::from("hello"), Selection::single(0, 1)),
print("#[h|]#ello")
parse_selection_string("#[h|]#ello").unwrap()
);
assert_eq!(
(String::from("hello"), Selection::single(4, 0)),
print("#[|hell]#o")
parse_selection_string("#[|hell]#o").unwrap()
);
assert_eq!(
(String::from("hello"), Selection::single(0, 4)),
print("#[hell|]#o")
parse_selection_string("#[hell|]#o").unwrap()
);
assert_eq!(
(String::from("hello"), Selection::single(5, 0)),
print("#[|hello]#")
parse_selection_string("#[|hello]#").unwrap()
);
assert_eq!(
(String::from("hello"), Selection::single(0, 5)),
print("#[hello|]#")
parse_selection_string("#[hello|]#").unwrap()
);
}

Expand All @@ -221,7 +236,7 @@ mod test {
0
)
),
print("#[|h]#ell#(|o)#")
parse_selection_string("#[|h]#ell#(|o)#").unwrap()
);
assert_eq!(
(
Expand All @@ -231,7 +246,7 @@ mod test {
0
)
),
print("#[h|]#ell#(o|)#")
parse_selection_string("#[h|]#ell#(o|)#").unwrap()
);
assert_eq!(
(
Expand All @@ -241,7 +256,7 @@ mod test {
0
)
),
print("#[|he]#l#(|lo)#")
parse_selection_string("#[|he]#l#(|lo)#").unwrap()
);
assert_eq!(
(
Expand All @@ -255,31 +270,31 @@ mod test {
0
)
),
print("hello#[|\r\n]#hello#(|\r\n)#hello#(|\r\n)#")
parse_selection_string("hello#[|\r\n]#hello#(|\r\n)#hello#(|\r\n)#").unwrap()
);
}

#[test]
fn print_multi_byte_code_point() {
assert_eq!(
(String::from("„“"), Selection::single(1, 0)),
print("#[|„]#“")
parse_selection_string("#[|„]#“").unwrap()
);
assert_eq!(
(String::from("„“"), Selection::single(2, 1)),
print("„#[|“]#")
parse_selection_string("„#[|“]#").unwrap()
);
assert_eq!(
(String::from("„“"), Selection::single(0, 1)),
print("#[„|]#“")
parse_selection_string("#[„|]#“").unwrap()
);
assert_eq!(
(String::from("„“"), Selection::single(1, 2)),
print("„#[“|]#")
parse_selection_string("„#[“|]#").unwrap()
);
assert_eq!(
(String::from("they said „hello“"), Selection::single(11, 10)),
print("they said #[|„]#hello“")
parse_selection_string("they said #[|„]#hello“").unwrap()
);
}

Expand All @@ -290,7 +305,7 @@ mod test {
String::from("hello 👨‍👩‍👧‍👦 goodbye"),
Selection::single(13, 6)
),
print("hello #[|👨‍👩‍👧‍👦]# goodbye")
parse_selection_string("hello #[|👨‍👩‍👧‍👦]# goodbye").unwrap()
);
}

Expand Down
6 changes: 3 additions & 3 deletions helix-core/src/textobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ mod test {
];

for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let (s, selection) = crate::test::parse_selection_string(before).unwrap();
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| textobject_paragraph(text.slice(..), r, TextObject::Inside, 1));
Expand All @@ -458,7 +458,7 @@ mod test {
];

for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let (s, selection) = crate::test::parse_selection_string(before).unwrap();
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| textobject_paragraph(text.slice(..), r, TextObject::Inside, 2));
Expand Down Expand Up @@ -489,7 +489,7 @@ mod test {
];

for (before, expected) in tests {
let (s, selection) = crate::test::print(before);
let (s, selection) = crate::test::parse_selection_string(before).unwrap();
let text = Rope::from(s.as_str());
let selection = selection
.transform(|r| textobject_paragraph(text.slice(..), r, TextObject::Around, 1));
Expand Down
Loading