// Package hook manages hook scripts for scientific-surfing. package hook import ( "fmt" "os" "path/filepath" "strings" "gitea.epss.net.cn/klesh/ss/internal/editor" "gitea.epss.net.cn/klesh/ss/internal/storage" "gitea.epss.net.cn/klesh/ss/templates" ) // Manager manages hook scripts for scientific-surfing. type Manager struct { Storage *storage.Manager HooksDir string } // New creates a hook Manager rooted at the storage manager's config directory. func New(s *storage.Manager) *Manager { return &Manager{ Storage: s, HooksDir: filepath.Join(s.ConfigDir, "hooks"), } } // Init initializes the hooks directory by copying the embedded template hooks. func (m *Manager) Init() { entries, err := templates.Hooks.ReadDir("hooks") if err != nil { fmt.Printf("Template hooks directory not found: %v\n", err) return } if err := os.MkdirAll(m.HooksDir, 0o755); err != nil { fmt.Printf("Failed to create hooks directory: %v\n", err) return } copiedCount := 0 for _, entry := range entries { if entry.IsDir() { continue } destFile := filepath.Join(m.HooksDir, entry.Name()) if _, err := os.Stat(destFile); err == nil { fmt.Printf("Skipped (already exists): %s\n", entry.Name()) continue } content, err := templates.Hooks.ReadFile("hooks/" + entry.Name()) if err != nil { fmt.Printf("Failed to read template %s: %v\n", entry.Name(), err) continue } if err := os.WriteFile(destFile, content, 0o644); err != nil { fmt.Printf("Failed to copy %s: %v\n", entry.Name(), err) continue } copiedCount++ fmt.Printf("Copied: %s\n", entry.Name()) } fmt.Printf("\nInitialized hooks directory with %d new scripts.\n", copiedCount) fmt.Printf("Location: %s\n", m.HooksDir) } // ListHooks displays the hooks directory location and lists all hook scripts. func (m *Manager) ListHooks() { fmt.Printf("Hooks directory: %s\n", m.HooksDir) if _, err := os.Stat(m.HooksDir); os.IsNotExist(err) { fmt.Println("Hooks directory does not exist. Run 'init' to create it.") return } hookFiles := m.getHookFiles() if len(hookFiles) == 0 { fmt.Println("No hook scripts found.") return } fmt.Printf("\nFound %d hook script(s):\n", len(hookFiles)) for _, f := range hookFiles { fmt.Printf(" - %s\n", f) } } // Edit opens a hook script with the system default editor. func (m *Manager) Edit(scriptName string) { if _, err := os.Stat(m.HooksDir); os.IsNotExist(err) { fmt.Println("Hooks directory does not exist. Run 'init' to create it.") return } scriptPath := filepath.Join(m.HooksDir, scriptName) if _, err := os.Stat(scriptPath); os.IsNotExist(err) { m.printNotFound(scriptName) return } editor.OpenFileInEditor(scriptPath) } // Rm removes a hook script. func (m *Manager) Rm(scriptName string) { if _, err := os.Stat(m.HooksDir); os.IsNotExist(err) { fmt.Println("Hooks directory does not exist.") return } scriptPath := filepath.Join(m.HooksDir, scriptName) if _, err := os.Stat(scriptPath); os.IsNotExist(err) { m.printNotFound(scriptName) return } if err := os.Remove(scriptPath); err != nil { fmt.Printf("Failed to remove script: %v\n", err) return } fmt.Printf("Removed: %s\n", scriptName) } func (m *Manager) printNotFound(scriptName string) { fmt.Printf("Script '%s' not found.\n", scriptName) available := m.getHookFiles() if len(available) > 0 { fmt.Printf("Available scripts: %s\n", strings.Join(available, ", ")) } } func (m *Manager) getHookFiles() []string { entries, err := os.ReadDir(m.HooksDir) if err != nil { return nil } var files []string for _, entry := range entries { if !entry.IsDir() { files = append(files, entry.Name()) } } return files }