1use std::{fmt, str::FromStr};
4
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
8#[serde(rename_all = "kebab-case")]
9pub enum Dialect {
10 Claude,
11 #[serde(rename = "agent-skills", alias = "agentskills", alias = "agent_skills")]
13 AgentSkills,
14 Codex,
15 #[serde(rename = "opencode", alias = "open-code")]
17 OpenCode,
18 Cursor,
19 #[serde(rename = "mars-native", alias = "marsnative", alias = "mars_native")]
20 MarsNative,
21}
22
23impl Dialect {
24 pub fn as_str(self) -> &'static str {
25 match self {
26 Self::Claude => "claude",
27 Self::AgentSkills => "agent-skills",
28 Self::Codex => "codex",
29 Self::OpenCode => "opencode",
30 Self::Cursor => "cursor",
31 Self::MarsNative => "mars-native",
32 }
33 }
34
35 pub fn parse(name: &str) -> Option<Self> {
36 match name.trim().to_ascii_lowercase().as_str() {
37 "claude" => Some(Self::Claude),
38 "agent-skills" | "agentskills" | "agent_skills" => Some(Self::AgentSkills),
39 "codex" => Some(Self::Codex),
40 "opencode" => Some(Self::OpenCode),
41 "cursor" => Some(Self::Cursor),
42 "mars-native" | "marsnative" | "mars_native" => Some(Self::MarsNative),
43 _ => None,
44 }
45 }
46}
47
48#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
51pub struct DialectChoice {
52 pub dialect: Dialect,
53 pub evidence: DialectEvidence,
54}
55
56#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
57pub struct DialectEvidence {
58 pub source: DialectEvidenceSource,
59 pub paths: Vec<String>,
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
64#[serde(rename_all = "lowercase")]
65pub enum DialectEvidenceSource {
66 Declared,
67 Predicted,
68}
69
70impl DialectChoice {
71 pub(crate) fn declared(dialect: Dialect) -> Self {
72 Self {
73 dialect,
74 evidence: DialectEvidence {
75 source: DialectEvidenceSource::Declared,
76 paths: Vec::new(),
77 },
78 }
79 }
80
81 pub(crate) fn predicted(dialect: Dialect, paths: Vec<String>) -> Self {
82 Self {
83 dialect,
84 evidence: DialectEvidence {
85 source: DialectEvidenceSource::Predicted,
86 paths,
87 },
88 }
89 }
90}
91
92impl fmt::Display for Dialect {
93 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94 f.write_str(self.as_str())
95 }
96}
97
98impl FromStr for Dialect {
99 type Err = ();
100
101 fn from_str(value: &str) -> Result<Self, Self::Err> {
102 Self::parse(value).ok_or(())
103 }
104}