1pub fn missing_import_message(names: &[&str]) -> Option<String> {
17 const WHERE: &str = "https://www.music21.org/music21docs/installing/installAdditional.html";
18 match names {
19 [] => None,
20 [name] => Some(format!(
21 "Certain music21 functions might need the optional package {name};\n{}if you run \
22 into errors, install it by following the instructions at\n{}{WHERE}",
23 " ".repeat(18),
24 " ".repeat(18)
25 )),
26 _ => Some(format!(
27 "Certain music21 functions might need these optional packages: {};\n{}if you run \
28 into errors, install them by following the instructions at\n{}{WHERE}",
29 names.join(", "),
30 " ".repeat(19),
31 " ".repeat(19)
32 )),
33 }
34}
35
36pub fn platform_name() -> &'static str {
45 if cfg!(windows) {
46 return "win";
47 }
48 if cfg!(target_os = "macos") {
49 return "darwin";
50 }
51 if cfg!(unix) {
52 return "nix";
53 }
54 "other"
55}
56
57pub fn cleaned_flat_notation(text: &str) -> String {
68 let characters: Vec<char> = text.chars().collect();
69 let mut cleaned = String::with_capacity(text.len());
70 let mut index = 0;
71 while index < characters.len() {
72 let letter = characters[index];
73 cleaned.push(letter);
74 let flat =
75 matches!(letter, 'A'..='G' | 'a'..='g') && characters.get(index + 1) == Some(&'b');
76 if flat {
77 cleaned.push('-');
78 index += 2;
79 } else {
80 index += 1;
81 }
82 }
83 cleaned
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn several_missing_packages_are_listed_together() {
92 let message = missing_import_message(&["matplotlib", "numpy"]).unwrap();
93 let lines: Vec<&str> = message.lines().collect();
94 assert_eq!(
95 lines[0],
96 "Certain music21 functions might need these optional packages: matplotlib, numpy;"
97 );
98 assert_eq!(
99 lines[1],
100 " if you run into errors, install them by following the \
101 instructions at"
102 );
103 assert_eq!(lines.len(), 3);
104 }
105
106 #[test]
107 fn a_flat_is_only_a_b_after_a_note_letter() {
108 assert_eq!(cleaned_flat_notation("Bbb"), "B-b");
109 assert_eq!(cleaned_flat_notation("Hb abc"), "Hb a-c");
110 }
111}