github_languages/
macros.rs

1#[derive(Debug, Clone, PartialEq)]
2pub struct LanguageInfo {
3    pub name: &'static str,
4    pub r#type: &'static str,
5    pub color: &'static str,
6    pub extensions: &'static [&'static str],
7    pub aliases: &'static [&'static str],
8    pub tm_scope: &'static str,
9    pub ace_mode: &'static str,
10    pub language_id: u64,
11    pub codemirror_mode: Option<&'static str>,
12    pub codemirror_mime_type: Option<&'static str>,
13    pub wrap: Option<bool>,
14    pub filenames: &'static [&'static str],
15    pub group: Option<&'static str>,
16    pub interpreters: &'static [&'static str],
17    pub fs_name: Option<&'static str>,
18    pub searchable: Option<bool>,
19}
20
21#[macro_export]
22macro_rules! define_languages {
23    (
24        $(
25            $struct_name:ident => {
26                name: $name:literal,
27                r#type: $lang_type:literal,
28                color: $color:literal,
29                extensions: [ $( $ext:literal ),* $( , )? ],
30                aliases: [ $( $alias:literal ),* $( , )? ],
31                tm_scope: $tm_scope:literal,
32                ace_mode: $ace_mode:literal,
33                language_id: $id:literal,
34                $( codemirror_mode: $cm_mode:literal, )?
35                $( codemirror_mime_type: $cm_mime:literal, )?
36                $( wrap: $wrap:literal, )?
37                filenames: [ $( $filename:literal ),* $( , )? ],
38                $( group: $group:literal, )?
39                interpreters: [ $( $interp:literal ),* $( , )? ],
40                $( fs_name: $fs_name:literal, )?
41                $( searchable: $searchable:literal, )?
42            }
43        ),*
44        $( , )?
45    ) => {
46        use $crate::macros::LanguageInfo;
47        use once_cell::sync::Lazy;
48
49        // Generate simple language structs (no modules!)
50        $(
51            pub struct $struct_name;
52
53            impl $struct_name {
54                pub fn info() -> LanguageInfo {
55                    LanguageInfo {
56                        name: $name,
57                        r#type: $lang_type,
58                        color: $color,
59                        extensions: &[ $( $ext ),* ],
60                        aliases: &[ $( $alias ),* ],
61                        tm_scope: $tm_scope,
62                        ace_mode: $ace_mode,
63                        language_id: $id,
64                        codemirror_mode: None $(.or(Some($cm_mode)))?,
65                        codemirror_mime_type: None $(.or(Some($cm_mime)))?,
66                        wrap: None $(.or(Some($wrap)))?,
67                        filenames: &[ $( $filename ),* ],
68                        group: None $(.or(Some($group)))?,
69                        interpreters: &[ $( $interp ),* ],
70                        fs_name: None $(.or(Some($fs_name)))?,
71                        searchable: None $(.or(Some($searchable)))?,
72                    }
73                }
74            }
75        )*
76
77        // Single Languages struct
78        pub struct Languages;
79
80        impl Languages {
81            pub fn get_by_name(&self, name: &str) -> Option<LanguageInfo> {
82                BY_NAME.get(name).map(|f| f())
83            }
84
85            pub fn get_by_id(&self, id: u64) -> Option<LanguageInfo> {
86                BY_ID.get(&id).map(|f| f())
87            }
88
89            pub fn get_by_extension(&self, ext: &str) -> Vec<LanguageInfo> {
90                BY_EXTENSION
91                    .get(ext)
92                    .map(|funcs| funcs.iter().map(|f| f()).collect())
93                    .unwrap_or_default()
94            }
95
96            pub fn get_by_alias(&self, alias: &str) -> Vec<LanguageInfo> {
97                ALL_LANGUAGES.iter().filter(|lang| lang.aliases.contains(&alias)).cloned().collect()
98            }
99
100            pub fn get_by_filename(&self, filename: &str) -> Vec<LanguageInfo> {
101                ALL_LANGUAGES.iter().filter(|lang| lang.filenames.contains(&filename)).cloned().collect()
102            }
103
104            pub fn get_by_interpreter(&self, interpreter: &str) -> Vec<LanguageInfo> {
105                ALL_LANGUAGES.iter().filter(|lang| lang.interpreters.contains(&interpreter)).cloned().collect()
106            }
107
108            pub fn get_by_type(&self, r#type: &str) -> Vec<LanguageInfo> {
109                ALL_LANGUAGES.iter().filter(|lang| lang.r#type == r#type).cloned().collect()
110            }
111
112            pub fn all_languages(&self) -> &[LanguageInfo] {
113                &ALL_LANGUAGES
114            }
115        }
116
117        // Use Lazy initialization for the languages array
118        static ALL_LANGUAGES: Lazy<Vec<LanguageInfo>> = Lazy::new(|| vec![
119            $( $struct_name::info() ),*
120        ]);
121
122        static BY_NAME: phf::Map<&'static str, fn() -> LanguageInfo> = phf_map! {
123            $( $name => $struct_name::info ),*
124        };
125
126        static BY_ID: phf::Map<u64, fn() -> LanguageInfo> = phf_map! {
127            $( $id => $struct_name::info ),*
128        };
129
130        pub fn get_languages() -> Languages {
131            Languages
132        }
133
134        pub static LANGUAGES: Lazy<Languages> = Lazy::new(|| Languages);
135    };
136}