Skip to main content

mise_interactive_config/
providers.rs

1//! Provider traits for injecting external data into the editor
2//!
3//! These traits allow the main mise crate to inject data (like the tool registry)
4//! without creating circular dependencies.
5
6use async_trait::async_trait;
7
8/// Information about a tool from the registry
9#[derive(Debug, Clone)]
10pub struct ToolInfo {
11    /// Tool name (e.g., "node", "python")
12    pub name: String,
13    /// Short description of the tool
14    pub description: Option<String>,
15    /// Aliases for this tool
16    pub aliases: Vec<String>,
17}
18
19/// Information about a setting
20#[derive(Debug, Clone)]
21pub struct SettingInfo {
22    /// Setting name (e.g., "experimental", "jobs")
23    pub name: String,
24    /// Description of what this setting does
25    pub description: Option<String>,
26    /// Type of the setting (for display and validation)
27    pub setting_type: SettingType,
28    /// Default value as string
29    pub default: Option<String>,
30}
31
32/// Type of a setting value
33#[derive(Debug, Clone, PartialEq)]
34pub enum SettingType {
35    /// Boolean (true/false)
36    Bool,
37    /// Integer number
38    Integer,
39    /// String value
40    String,
41    /// Array of strings
42    StringArray,
43    /// Duration (e.g., "1h", "30m")
44    Duration,
45    /// Path on filesystem
46    Path,
47    /// Enum with specific allowed values
48    Enum(Vec<String>),
49}
50
51/// Information about a backend
52#[derive(Debug, Clone)]
53pub struct BackendInfo {
54    /// Backend name (e.g., "cargo", "npm")
55    pub name: String,
56    /// Description of the backend
57    pub description: Option<String>,
58}
59
60/// Provider for tool information from the registry
61pub trait ToolProvider: Send + Sync {
62    /// List all available tools
63    fn list_tools(&self) -> Vec<ToolInfo>;
64}
65
66/// Provider for backend information
67pub trait BackendProvider: Send + Sync {
68    /// List all available backends
69    fn list_backends(&self) -> Vec<BackendInfo>;
70}
71
72/// Default empty backend provider
73pub struct EmptyBackendProvider;
74
75impl BackendProvider for EmptyBackendProvider {
76    fn list_backends(&self) -> Vec<BackendInfo> {
77        Vec::new()
78    }
79}
80
81/// Provider for setting information
82pub trait SettingProvider: Send + Sync {
83    /// List all available settings
84    fn list_settings(&self) -> Vec<SettingInfo>;
85}
86
87/// Default empty tool provider (no tools available)
88pub struct EmptyToolProvider;
89
90impl ToolProvider for EmptyToolProvider {
91    fn list_tools(&self) -> Vec<ToolInfo> {
92        Vec::new()
93    }
94}
95
96/// Default empty setting provider (no settings available)
97pub struct EmptySettingProvider;
98
99impl SettingProvider for EmptySettingProvider {
100    fn list_settings(&self) -> Vec<SettingInfo> {
101        Vec::new()
102    }
103}
104
105/// Provider for tool version information
106#[async_trait]
107pub trait VersionProvider: Send + Sync {
108    /// Get the latest version of a tool
109    ///
110    /// Returns the full version string (e.g., "3.12.4" for python)
111    async fn latest_version(&self, tool: &str) -> Option<String>;
112}
113
114/// Default empty version provider
115pub struct EmptyVersionProvider;
116
117#[async_trait]
118impl VersionProvider for EmptyVersionProvider {
119    async fn latest_version(&self, _tool: &str) -> Option<String> {
120        None
121    }
122}
123
124/// Marker for the custom version entry option
125pub const VERSION_CUSTOM_MARKER: &str = "other...";
126
127/// Generate version variants from a full version string
128///
129/// Given "3.12.4", returns ["latest", "3", "3.12", "3.12.4", "other..."]
130pub fn version_variants(full_version: &str) -> Vec<String> {
131    let mut variants = vec!["latest".to_string()];
132
133    // Parse version segments
134    let parts: Vec<&str> = full_version.split('.').collect();
135
136    // Build progressive versions
137    let mut current = String::new();
138    for (i, part) in parts.iter().enumerate() {
139        if i > 0 {
140            current.push('.');
141        }
142        current.push_str(part);
143        variants.push(current.clone());
144    }
145
146    // Add custom entry option at the end
147    variants.push(VERSION_CUSTOM_MARKER.to_string());
148
149    variants
150}