feat(deps): implement dependency auto-completion and interactive installation CLI (#147)
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
package deps
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Detector 依赖检测器接口
|
||||
type Detector interface {
|
||||
Detect(logContent string) []string
|
||||
}
|
||||
|
||||
// PythonDetector Python 依赖检测器
|
||||
type PythonDetector struct{}
|
||||
|
||||
func (d *PythonDetector) Detect(logContent string) []string {
|
||||
var pkgs []string
|
||||
seen := make(map[string]bool)
|
||||
pythonRegex1 := regexp.MustCompile(`ModuleNotFoundError: No module named '([^']+)'`)
|
||||
pythonRegex2 := regexp.MustCompile(`No module named ([a-zA-Z0-9_\-]+)`)
|
||||
|
||||
matches := pythonRegex1.FindAllStringSubmatch(logContent, -1)
|
||||
for _, m := range matches {
|
||||
if len(m) > 1 {
|
||||
name := strings.TrimSpace(m[1])
|
||||
if name != "" && !seen[name] {
|
||||
seen[name] = true
|
||||
pkgs = append(pkgs, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
matches2 := pythonRegex2.FindAllStringSubmatch(logContent, -1)
|
||||
for _, m := range matches2 {
|
||||
if len(m) > 1 {
|
||||
name := strings.TrimSpace(m[1])
|
||||
if name != "" && !seen[name] {
|
||||
seen[name] = true
|
||||
pkgs = append(pkgs, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// NodeDetector Node.js 依赖检测器
|
||||
type NodeDetector struct{}
|
||||
|
||||
func (d *NodeDetector) Detect(logContent string) []string {
|
||||
var pkgs []string
|
||||
seen := make(map[string]bool)
|
||||
nodeRegex1 := regexp.MustCompile(`Error: Cannot find module '([^']+)'`)
|
||||
nodeRegex2 := regexp.MustCompile(`Cannot find module '([^']+)'`)
|
||||
|
||||
matches := nodeRegex1.FindAllStringSubmatch(logContent, -1)
|
||||
for _, m := range matches {
|
||||
if len(m) > 1 {
|
||||
name := strings.TrimSpace(m[1])
|
||||
if name != "" && !seen[name] {
|
||||
seen[name] = true
|
||||
pkgs = append(pkgs, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
matches2 := nodeRegex2.FindAllStringSubmatch(logContent, -1)
|
||||
for _, m := range matches2 {
|
||||
if len(m) > 1 {
|
||||
name := strings.TrimSpace(m[1])
|
||||
if name != "" && !seen[name] {
|
||||
seen[name] = true
|
||||
pkgs = append(pkgs, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return pkgs
|
||||
}
|
||||
|
||||
var languageDetectors = map[string]Detector{
|
||||
"python": &PythonDetector{},
|
||||
"python3": &PythonDetector{},
|
||||
"node": &NodeDetector{},
|
||||
"js": &NodeDetector{},
|
||||
"ts": &NodeDetector{},
|
||||
"bun": &NodeDetector{},
|
||||
}
|
||||
|
||||
// DetectMissingDependencies 从日志内容中检测缺失的依赖包名
|
||||
func DetectMissingDependencies(language, logContent string) ([]string, bool) {
|
||||
lang := strings.ToLower(language)
|
||||
var det Detector
|
||||
for key, d := range languageDetectors {
|
||||
if strings.Contains(lang, key) {
|
||||
det = d
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if det == nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
pkgs := det.Detect(logContent)
|
||||
return pkgs, len(pkgs) > 0
|
||||
}
|
||||
Reference in New Issue
Block a user