@@ -50,14 +50,11 @@ pub struct Snippet<'a> {
5050 elements: Vec<SnippetElement<'a>>,
5151}
5252
53−pub fn parse<'a>(s: &'a str) -> Result<Snippet<'a>> {
53+pub fn parse(s: &str) -> Result<Snippet<'_>> {
5454 parser::parse(s).map_err(|rest| anyhow!("Failed to parse snippet. Remaining input: {}", rest))
5555}
5656
5757mod parser {
58− use helix_core::regex;
59− use once_cell::sync::Lazy;
60−
6158 use helix_parsec::*;
6259
6360 use super::{CaseChange, FormatItem, Regex, Snippet, SnippetElement};
@@ -86,17 +83,34 @@ mod parser {
8683 else ::= text
8784 */
8885
89− static DIGIT: Lazy<regex::Regex> = Lazy::new(|| regex::Regex::new(r"^[0-9]+").unwrap());
90− static VARIABLE: Lazy<regex::Regex> =
91− Lazy::new(|| regex::Regex::new(r"^[_a-zA-Z][_a-zA-Z0-9]*").unwrap());
92− static TEXT: Lazy<regex::Regex> = Lazy::new(|| regex::Regex::new(r"^[^\$]+").unwrap());
93−
9486 fn var<'a>() -> impl Parser<'a, Output = &'a str> {
95− pattern(&VARIABLE)
87+ // var = [_a-zA-Z][_a-zA-Z0-9]*
88+ move |input: &'a str| match input
89+ .char_indices()
90+ .take_while(|(p, c)| {
91+ *c == '_'
92+ || if *p == 0 {
93+ c.is_ascii_alphabetic()
94+ } else {
95+ c.is_ascii_alphanumeric()
96+ }
97+ })
98+ .last()
99+ {
100+ Some((index, c)) if index >= 1 => {
101+ let index = index + c.len_utf8();
102+ Ok((&input[index..], &input[0..index]))
103+ }
104+ _ => Err(input),
105+ }
106+ }
107+
108+ fn text<'a>() -> impl Parser<'a, Output = &'a str> {
109+ take_while(|c| c != '$')
96110 }
97111
98112 fn digit<'a>() -> impl Parser<'a, Output = usize> {
99− filter_map(pattern(&DIGIT), |s| s.parse().ok())
113+ filter_map(take_while(|c| c.is_ascii_digit()), |s| s.parse().ok())
100114 }
101115
102116 fn case_change<'a>() -> impl Parser<'a, Output = CaseChange> {
@@ -152,7 +166,7 @@ mod parser {
152166 |seq| { Conditional(seq.1, None, Some(seq.4)) }
153167 ),
154168 // Any text
155− map(pattern(&TEXT), Text),
169+ map(text(), Text),
156170 )
157171 }
158172
@@ -245,12 +259,9 @@ mod parser {
245259 )
246260 }
247261
248− fn text<'a>() -> impl Parser<'a, Output = SnippetElement<'a>> {
249− map(pattern(&TEXT), SnippetElement::Text)
250− }
251−
252262 fn anything<'a>() -> impl Parser<'a, Output = SnippetElement<'a>> {
253− choice!(tabstop(), placeholder(), choice(), variable(), text())
263+ let text = map(text(), SnippetElement::Text);
264+ choice!(tabstop(), placeholder(), choice(), variable(), text)
254265 }
255266
256267 fn snippet<'a>() -> impl Parser<'a, Output = Snippet<'a>> {