Skip to main content

only_syntax/
builtin.rs

1//! Typed definitions for the built-in Only language vocabulary.
2//!
3//! Parsers and higher layers keep unknown names in the `Unknown` variants so
4//! diagnostics can report the original spelling without duplicating string
5//! tables across the workspace.
6
7use std::fmt;
8
9use smol_str::SmolStr;
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
12pub enum DirectiveKind {
13    Version,
14    Var,
15    Shell,
16    Unknown(SmolStr),
17}
18
19impl DirectiveKind {
20    pub const SUPPORTED: &'static [Self] = &[Self::Version, Self::Var, Self::Shell];
21
22    pub fn parse(name: &str) -> Self {
23        match name {
24            "version" => Self::Version,
25            "var" => Self::Var,
26            "shell" => Self::Shell,
27            unknown => Self::Unknown(SmolStr::new(unknown)),
28        }
29    }
30
31    pub fn as_str(&self) -> &str {
32        match self {
33            Self::Version => "version",
34            Self::Var => "var",
35            Self::Shell => "shell",
36            Self::Unknown(name) => name,
37        }
38    }
39
40    pub fn is_supported(&self) -> bool {
41        !matches!(self, Self::Unknown(_))
42    }
43
44    pub fn description(&self) -> Option<&'static str> {
45        match self {
46            Self::Version => {
47                Some("Declares the minimum Onlyfile language capability required by this file.")
48            }
49            Self::Var => Some("Defines a global string value."),
50            Self::Shell => Some("Sets the default shell used for task commands."),
51            Self::Unknown(_) => None,
52        }
53    }
54}
55
56impl fmt::Display for DirectiveKind {
57    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
58        formatter.write_str(self.as_str())
59    }
60}
61
62#[derive(Debug, Clone, PartialEq, Eq, Hash)]
63pub enum GuardKind {
64    Os,
65    Arch,
66    Env,
67    Has,
68    Unknown(SmolStr),
69}
70
71impl GuardKind {
72    pub const SUPPORTED: &'static [Self] = &[Self::Os, Self::Arch, Self::Env, Self::Has];
73
74    pub fn parse(name: &str) -> Self {
75        match name {
76            "os" => Self::Os,
77            "arch" => Self::Arch,
78            "env" => Self::Env,
79            "has" => Self::Has,
80            unknown => Self::Unknown(SmolStr::new(unknown)),
81        }
82    }
83
84    pub fn as_str(&self) -> &str {
85        match self {
86            Self::Os => "os",
87            Self::Arch => "arch",
88            Self::Env => "env",
89            Self::Has => "has",
90            Self::Unknown(name) => name,
91        }
92    }
93
94    pub fn is_supported(&self) -> bool {
95        !matches!(self, Self::Unknown(_))
96    }
97
98    pub fn description(&self) -> Option<&'static str> {
99        match self {
100            Self::Os => Some("Checks the current operating system."),
101            Self::Arch => Some("Checks the current CPU architecture."),
102            Self::Env => Some("Checks whether an environment variable exists."),
103            Self::Has => Some("Checks whether a command is available."),
104            Self::Unknown(_) => None,
105        }
106    }
107}
108
109impl fmt::Display for GuardKind {
110    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
111        formatter.write_str(self.as_str())
112    }
113}
114
115#[derive(Debug, Clone, PartialEq, Eq)]
116pub enum ShellKind {
117    Deno,
118    Bash,
119    Sh,
120    Pwsh,
121    Powershell,
122    Unknown(SmolStr),
123}
124
125impl ShellKind {
126    pub const SUPPORTED: &'static [Self] = &[
127        Self::Deno,
128        Self::Bash,
129        Self::Sh,
130        Self::Pwsh,
131        Self::Powershell,
132    ];
133
134    pub fn parse(name: &str) -> Self {
135        match name {
136            "deno" => Self::Deno,
137            "bash" => Self::Bash,
138            "sh" => Self::Sh,
139            "pwsh" => Self::Pwsh,
140            "powershell" => Self::Powershell,
141            unknown => Self::Unknown(SmolStr::new(unknown)),
142        }
143    }
144
145    pub fn as_str(&self) -> &str {
146        match self {
147            Self::Deno => "deno",
148            Self::Bash => "bash",
149            Self::Sh => "sh",
150            Self::Pwsh => "pwsh",
151            Self::Powershell => "powershell",
152            Self::Unknown(name) => name,
153        }
154    }
155
156    pub fn fallback(&self) -> Option<Self> {
157        match self {
158            Self::Pwsh => Some(Self::Powershell),
159            Self::Bash => Some(Self::Sh),
160            _ => None,
161        }
162    }
163
164    pub fn is_supported(&self) -> bool {
165        !matches!(self, Self::Unknown(_))
166    }
167
168    pub fn description(&self) -> Option<&'static str> {
169        match self {
170            Self::Deno => Some("Runs commands with Deno."),
171            Self::Bash => Some("Runs commands with Bash."),
172            Self::Sh => Some("Runs commands with the system sh."),
173            Self::Pwsh => Some("Runs commands with PowerShell Core."),
174            Self::Powershell => Some("Runs commands with Windows PowerShell."),
175            Self::Unknown(_) => None,
176        }
177    }
178}
179
180impl fmt::Display for ShellKind {
181    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
182        formatter.write_str(self.as_str())
183    }
184}
185
186#[derive(Debug, Clone, Copy, PartialEq, Eq)]
187pub enum ShellOperator {
188    Required,
189    Fallback,
190}
191
192#[derive(Debug, Clone, PartialEq, Eq)]
193pub struct ShellSelection {
194    pub kind: ShellKind,
195    pub operator: ShellOperator,
196}
197
198impl ShellSelection {
199    pub fn required(kind: ShellKind) -> Self {
200        Self {
201            kind,
202            operator: ShellOperator::Required,
203        }
204    }
205}
206
207impl ShellOperator {
208    pub fn as_str(self) -> &'static str {
209        match self {
210            Self::Required => "shell=",
211            Self::Fallback => "shell~=",
212        }
213    }
214}
215
216impl fmt::Display for ShellOperator {
217    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
218        formatter.write_str(self.as_str())
219    }
220}
221
222#[derive(Debug, Clone, PartialEq, Eq)]
223pub struct TaskShellRef {
224    pub selection: ShellSelection,
225    pub range: text_size::TextRange,
226}