gig-gitignore工具实战开发(三):gig add基础实现

发布于:2025-07-28 ⋅ 阅读:(15) ⋅ 点赞:(0)

gig-gitignore工具实战开发(三):gig add基础实现

前言: 在上一篇我们已经设计了多源模板系统,本篇我们来进行实战。先实现gig add命令基础代码。

一、项目初始化

暂略,主要包含如下工作

  • go mod init 项目初始化
  • 添加cobra、viper等相关库
  • 配置初始化等等

参考依赖

require (
	github.com/manifoldco/promptui v0.9.0
	github.com/nicksnyder/go-i18n/v2 v2.6.0
	github.com/rivo/tview v0.0.0-20240307173318-e804876934a1
	github.com/sergi/go-diff v1.4.0
	github.com/spf13/afero v1.12.0
	github.com/spf13/cobra v1.9.1
	github.com/spf13/viper v1.20.1
	golang.org/x/text v0.23.0
	gopkg.in/yaml.v3 v3.0.1
)

二、add命令实现

添加add.go

命令行中调用

cobra-cli add add

添加参数

func init() {
	rootCmd.AddCommand(addCmd)
	addCmd.Flags().BoolVar(&yesFlag, "yes", false, "自动确认所有交互,无需人工输入")
	addCmd.Flags().BoolVarP(&updateFlag, "update", "u", false, "强制更新github模板")
}
  • yes参数可以忽略交互,适合自动化流程
  • update主要针对github模板,默认不进行更新

业务逻辑处理

根据传入参数不同,分别进行处理

func(cmd *cobra.Command, args []string) {
		var languages []string
		if len(args) == 0 {
			detected := utils.DetectionUtil.DetectProjectTypes(models.AppConfig.Detection.FileMap)
			if len(detected) > 0 {
				languages = promptUserForTypes(detected)
			}
			if len(languages) == 0 {
				fmt.Println("未检测到项目类型,请手动输入语言参数。例如:gig add python")
				os.Exit(1)
			}
		} else {
			languages = args
		}

		switch genType {
		case "ai":
			result, err := utils.AI.StreamChat("add", strings.Join(languages, ", "))
			if err != nil {
				fmt.Println("AI 生成失败:", err)
				os.Exit(1)
			}
			cleanedContent := cleanupAIOutput(result)
			updateGitignoreWithContent(cleanedContent)
		case "github":
			handleAdd(languages, "github", updateFlag)
		case "local":
			handleAdd(languages, "local", false)
		case "api":
			result, err := getGitignoreFromAPI(languages)
			if err != nil {
				fmt.Println("API 获取失败:", err)
				os.Exit(1)
			}
			updateGitignoreWithContent(result)
		default:
			fmt.Printf("Error: Invalid type '%s'. Please use 'local', 'github', 'ai' 或 'api'.\n", genType)
		}
	},
}

其中代码需要进行识别项目语言,我们进行如下工具封装,根据核心特征进行判断。由于项目繁多,不可能包括所有,用户可以自行进行核心特征拓展。

// 自动识别项目类型(递归遍历,仅根据配置文件匹配,特殊目录优化)
func (d Detection) DetectProjectTypes(fileMap map[string]string) []string {
	fmt.Println("typeMap:", fileMap)
	if len(fileMap) == 0 {
		// 配置为空时兜底
		return nil
	}

	langSet := make(map[string]struct{})

	// 特殊目录与类型的映射(可扩展)
	specialDirs := map[string]string{
		"node_modules": "node",
		// 可按需添加:
		// ".venv": "python",
		// "vendor": "go",
		// "target": "rust",
	}

	filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return nil // 忽略错误
		}
		if info.IsDir() {
			base := filepath.Base(path)
			// 跳过隐藏目录(如.git、.idea等)
			if strings.HasPrefix(base, ".") && path != "." {
				return filepath.SkipDir
			}
			// 特殊目录:遇到直接判定类型并跳过递归
			if lang, ok := specialDirs[base]; ok {
				langSet[lang] = struct{}{}
				return filepath.SkipDir
			}
			return nil
		}

		name := info.Name()
		if lang, ok := fileMap[name]; ok {
			langSet[lang] = struct{}{}
		}
		return nil
	})

	var langs []string
	for lang := range langSet {
		langs = append(langs, lang)
	}
	return langs
}

识别出的语言有可能有误,这时候用户可以进行修正

func promptUserForTypes(detected []string) []string {
	if yesFlag {
		fmt.Printf("检测到以下项目类型:%s\n", strings.Join(detected, ", "))
		fmt.Println("已自动确认项目类型 (--yes)")
		return detected
	}
	fmt.Printf("检测到以下项目类型:%s\n", strings.Join(detected, ", "))
	fmt.Print("是否确认?(直接回车确认,或输入新的类型列表,如:go,python):")
	input, _ := bufio.NewReader(os.Stdin).ReadString('\n')
	input = strings.TrimSpace(input)
	if input == "" {
		return detected
	}
	var result []string
	for _, t := range strings.Split(input, ",") {
		t = strings.TrimSpace(t)
		if t != "" {
			result = append(result, t)
		}
	}
	return result
}

网站公告

今日签到

点亮在社区的每一天
去签到