package plugins import ( "fmt" "sort" "sync" ) // Registry manages language plugin registration type Registry struct { mu sync.RWMutex plugins map[string]LanguagePlugin } // Global registry instance var globalRegistry = &Registry{ plugins: make(map[string]LanguagePlugin), } // Register registers a language plugin func Register(plugin LanguagePlugin) error { globalRegistry.mu.Lock() defer globalRegistry.mu.Unlock() name := plugin.Name() if _, exists := globalRegistry.plugins[name]; exists { return fmt.Errorf("plugin %s already registered", name) } globalRegistry.plugins[name] = plugin return nil } // Get retrieves a plugin by name func Get(name string) (LanguagePlugin, bool) { globalRegistry.mu.RLock() defer globalRegistry.mu.RUnlock() plugin, ok := globalRegistry.plugins[name] return plugin, ok } // All returns all registered plugins func All() []LanguagePlugin { globalRegistry.mu.RLock() defer globalRegistry.mu.RUnlock() plugins := make([]LanguagePlugin, 0, len(globalRegistry.plugins)) for _, p := range globalRegistry.plugins { plugins = append(plugins, p) } // Sort by name for consistent ordering sort.Slice(plugins, func(i, j int) bool { return plugins[i].Name() < plugins[j].Name() }) return plugins } // Names returns all registered plugin names func Names() []string { globalRegistry.mu.RLock() defer globalRegistry.mu.RUnlock() names := make([]string, 0, len(globalRegistry.plugins)) for name := range globalRegistry.plugins { names = append(names, name) } sort.Strings(names) return names } // DetectLanguage attempts to detect the language from a path func DetectLanguage(path string) string { globalRegistry.mu.RLock() defer globalRegistry.mu.RUnlock() // Check marker files for each plugin for _, plugin := range globalRegistry.plugins { for _, marker := range plugin.MarkerFiles() { // Check if marker file exists if fileExists(path + "/" + marker) { return plugin.Name() } } } // Default to first registered plugin for name := range globalRegistry.plugins { return name } return "" } // GetForExtension returns the plugin for a given file extension func GetForExtension(ext string) LanguagePlugin { globalRegistry.mu.RLock() defer globalRegistry.mu.RUnlock() for _, plugin := range globalRegistry.plugins { for _, pluginExt := range plugin.Extensions() { if pluginExt == ext { return plugin } } } return nil } // fileExists is a simple helper - will be replaced with proper implementation func fileExists(path string) bool { // This will be replaced with actual file existence check return false }