Skip to main content

mq_edit/document/
file_type.rs

1use std::path::Path;
2
3/// File type classification
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum FileType {
6    /// Markdown file
7    Markdown,
8    /// Code file with language identifier
9    Code(String),
10    /// Plain text file
11    PlainText,
12}
13
14impl FileType {
15    /// Detect file type from file extension
16    pub fn from_path(path: &Path) -> Self {
17        match path.extension().and_then(|e| e.to_str()) {
18            Some("md") | Some("markdown") => FileType::Markdown,
19            Some("mq") => FileType::Code("mq".to_string()),
20            Some("rs") => FileType::Code("rust".to_string()),
21            Some("py") => FileType::Code("python".to_string()),
22            Some("js") => FileType::Code("javascript".to_string()),
23            Some("ts") => FileType::Code("typescript".to_string()),
24            Some("tsx") => FileType::Code("typescriptreact".to_string()),
25            Some("jsx") => FileType::Code("javascriptreact".to_string()),
26            Some("go") => FileType::Code("go".to_string()),
27            Some("java") => FileType::Code("java".to_string()),
28            Some("cpp") | Some("cc") | Some("cxx") | Some("c++") => {
29                FileType::Code("cpp".to_string())
30            }
31            Some("c") => FileType::Code("c".to_string()),
32            Some("h") | Some("hpp") | Some("hxx") => FileType::Code("cpp".to_string()),
33            Some("json") => FileType::Code("json".to_string()),
34            Some("toml") => FileType::Code("toml".to_string()),
35            Some("yaml") | Some("yml") => FileType::Code("yaml".to_string()),
36            Some("html") => FileType::Code("html".to_string()),
37            Some("css") => FileType::Code("css".to_string()),
38            Some("xml") => FileType::Code("xml".to_string()),
39            Some("sh") | Some("bash") => FileType::Code("bash".to_string()),
40            Some("rb") => FileType::Code("ruby".to_string()),
41            Some("php") => FileType::Code("php".to_string()),
42            Some("swift") => FileType::Code("swift".to_string()),
43            Some("kt") | Some("kts") => FileType::Code("kotlin".to_string()),
44            Some("scala") => FileType::Code("scala".to_string()),
45            Some("hs") => FileType::Code("haskell".to_string()),
46            Some("elm") => FileType::Code("elm".to_string()),
47            Some("vim") => FileType::Code("vim".to_string()),
48            Some("lua") => FileType::Code("lua".to_string()),
49            Some("txt") | Some("text") => FileType::PlainText,
50            _ => FileType::PlainText,
51        }
52    }
53
54    /// Get LSP language identifier
55    ///
56    /// Returns the language identifier that should be used with LSP servers.
57    /// This follows the LSP specification for language identifiers.
58    pub fn lsp_language_id(&self) -> Option<&str> {
59        match self {
60            FileType::Code(lang) => Some(lang.as_str()),
61            FileType::Markdown => Some("markdown"),
62            FileType::PlainText => None,
63        }
64    }
65
66    /// Get human-readable name for this file type
67    pub fn display_name(&self) -> &str {
68        match self {
69            FileType::Markdown => "Markdown",
70            FileType::Code(lang) => lang.as_str(),
71            FileType::PlainText => "Plain Text",
72        }
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79    use std::path::PathBuf;
80
81    #[test]
82    fn test_markdown_detection() {
83        assert_eq!(
84            FileType::from_path(&PathBuf::from("file.md")),
85            FileType::Markdown
86        );
87        assert_eq!(
88            FileType::from_path(&PathBuf::from("README.markdown")),
89            FileType::Markdown
90        );
91    }
92
93    #[test]
94    fn test_code_detection() {
95        assert_eq!(
96            FileType::from_path(&PathBuf::from("main.rs")),
97            FileType::Code("rust".to_string())
98        );
99        assert_eq!(
100            FileType::from_path(&PathBuf::from("script.py")),
101            FileType::Code("python".to_string())
102        );
103        assert_eq!(
104            FileType::from_path(&PathBuf::from("app.ts")),
105            FileType::Code("typescript".to_string())
106        );
107        assert_eq!(
108            FileType::from_path(&PathBuf::from("query.mq")),
109            FileType::Code("mq".to_string())
110        );
111    }
112
113    #[test]
114    fn test_plain_text_detection() {
115        assert_eq!(
116            FileType::from_path(&PathBuf::from("notes.txt")),
117            FileType::PlainText
118        );
119        assert_eq!(
120            FileType::from_path(&PathBuf::from("file.unknown")),
121            FileType::PlainText
122        );
123    }
124
125    #[test]
126    fn test_lsp_language_id() {
127        assert_eq!(
128            FileType::Code("rust".to_string()).lsp_language_id(),
129            Some("rust")
130        );
131        assert_eq!(FileType::Markdown.lsp_language_id(), Some("markdown"));
132        assert_eq!(FileType::PlainText.lsp_language_id(), None);
133    }
134}