1use std::borrow::Cow;
2use std::mem;
3
4use lazy_static::lazy_static;
5
6use percent_encoding::percent_decode;
7use regex::Regex;
8
9use crate::shell;
10
11pub fn split_at_comma(source: &str) -> Vec<String> {
13 let mut items = Vec::new();
14
15 let mut escaped = false;
16 let mut item = String::new();
17
18 for ch in source.chars() {
19 if ch == ',' && !escaped {
20 item = item.replace("\\,", ",");
21
22 let mut new_item = String::new();
23 mem::swap(&mut item, &mut new_item);
24
25 items.push(new_item);
26 } else {
27 item.push(ch);
28 }
29 escaped = ch == '\\';
30 }
31
32 if !item.is_empty() {
33 items.push(item.replace("\\,", ","));
34 }
35
36 items
37}
38
39pub fn escape_filename<'t>(filename: &'t str) -> Cow<'t, str> {
41 lazy_static! {
42 static ref SPECIAL_CHARS: Regex = if cfg!(target_os = "windows") {
43 Regex::new(r"[[:ascii:]&&[^0-9a-zA-Z._:\\-]]").unwrap()
45 } else {
46 Regex::new(r"[[:ascii:]&&[^0-9a-zA-Z._/-]]").unwrap()
48 };
49 }
50 SPECIAL_CHARS.replace_all(&*filename, r"\$0")
51}
52
53pub fn decode_uri(uri: &str) -> Option<String> {
58 let path = match uri.split_at(8) {
59 ("file:///", path) => path,
60 _ => return None,
61 };
62 let path = percent_decode(path.as_bytes()).decode_utf8().ok()?;
63 if cfg!(target_os = "windows") {
64 lazy_static! {
65 static ref SLASH: Regex = Regex::new(r"/").unwrap();
66 }
67 Some(String::from(SLASH.replace_all(&*path, r"\")))
68 } else {
69 Some("/".to_owned() + &path)
70 }
71}
72
73pub fn about_comments() -> String {
75 format!(
76 "Build on top of neovim\n\
77 Minimum supported neovim version: {}",
78 shell::MINIMUM_SUPPORTED_NVIM_VERSION
79 )
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn test_comma_split() {
88 let res = split_at_comma("a,b");
89 assert_eq!(2, res.len());
90 assert_eq!("a", res[0]);
91 assert_eq!("b", res[1]);
92
93 let res = split_at_comma("a,b\\,c");
94 assert_eq!(2, res.len());
95 assert_eq!("a", res[0]);
96 assert_eq!("b,c", res[1]);
97 }
98}