panache_parser/parser/utils/
helpers.rs1use crate::syntax::SyntaxKind;
4use rowan::GreenNodeBuilder;
5
6pub(crate) fn emit_line_tokens(builder: &mut GreenNodeBuilder<'static>, line: &str) {
9 if let Some(text) = line.strip_suffix("\r\n") {
11 builder.token(SyntaxKind::TEXT.into(), text);
12 builder.token(SyntaxKind::NEWLINE.into(), "\r\n");
13 } else if let Some(text) = line.strip_suffix('\n') {
14 builder.token(SyntaxKind::TEXT.into(), text);
15 builder.token(SyntaxKind::NEWLINE.into(), "\n");
16 } else {
17 builder.token(SyntaxKind::TEXT.into(), line);
19 }
20}
21
22pub(crate) fn strip_leading_spaces_n(line: &str, max_spaces: usize) -> &str {
25 let spaces_to_strip = line
26 .chars()
27 .take(max_spaces)
28 .take_while(|&c| c == ' ')
29 .count();
30 &line[spaces_to_strip..]
31}
32
33pub(crate) fn strip_leading_spaces(line: &str) -> &str {
36 strip_leading_spaces_n(line, 3)
37}
38
39pub(crate) fn strip_newline(line: &str) -> (&str, &str) {
42 if let Some(content) = line.strip_suffix("\r\n") {
43 (content, "\r\n")
44 } else if let Some(content) = line.strip_suffix('\n') {
45 (content, "\n")
46 } else {
47 (line, "")
48 }
49}
50
51pub(crate) fn split_lines_inclusive(input: &str) -> Vec<&str> {
54 if input.is_empty() {
55 return vec![];
56 }
57
58 let mut lines = Vec::new();
59 let mut start = 0;
60 let bytes = input.as_bytes();
61 let len = bytes.len();
62
63 let mut i = 0;
64 while i < len {
65 if bytes[i] == b'\n' {
66 lines.push(&input[start..=i]);
68 start = i + 1;
69 i += 1;
70 } else if bytes[i] == b'\r' && i + 1 < len && bytes[i + 1] == b'\n' {
71 lines.push(&input[start..=i + 1]);
73 start = i + 2;
74 i += 2;
75 } else {
76 i += 1;
77 }
78 }
79
80 if start < len {
82 lines.push(&input[start..]);
83 }
84
85 lines
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_strip_leading_spaces_n() {
94 assert_eq!(strip_leading_spaces_n(" text", 3), "text");
95 assert_eq!(strip_leading_spaces_n(" text", 3), "text");
96 assert_eq!(strip_leading_spaces_n(" text", 3), "text");
97 assert_eq!(strip_leading_spaces_n("text", 3), "text");
98 assert_eq!(strip_leading_spaces_n(" text", 3), " text");
99 }
100
101 #[test]
102 fn test_strip_newline() {
103 assert_eq!(strip_newline("text\n"), ("text", "\n"));
104 assert_eq!(strip_newline("text\r\n"), ("text", "\r\n"));
105 assert_eq!(strip_newline("text"), ("text", ""));
106 }
107}