diff --git a/README.md b/README.md index 6772356..c16544d 100644 --- a/README.md +++ b/README.md @@ -178,7 +178,7 @@ git-commit-helper translate /path/to/existing/file # 文件路径 | 命令 | 说明 | 示例 | |------|------|------| -| config | 配置 AI 服务 | `git-commit-helper config [--set-only-chinese ]` | +| config | 配置 AI 服务 | `git-commit-helper config [--set-only-chinese /--set-only-english ]` | | show | 显示当前配置 | `git-commit-helper show` | | install | 安装 Git Hook | `git-commit-helper install [-f]` | | ai add | 添加 AI 服务 | `git-commit-helper ai add` | @@ -189,7 +189,7 @@ git-commit-helper translate /path/to/existing/file # 文件路径 | ai list | 列出所有服务 | `git-commit-helper ai list` | | ai test | 测试指定服务 | `git-commit-helper ai test [-t "测试文本"]` | | translate | 翻译内容 | `git-commit-helper translate [-f 文件] [-t 文本]` | -| commit | 生成提交信息 | `git-commit-helper commit [-t 类型] [-m 描述] [-a] [--no-review]` | +| commit | 生成提交信息 | `git-commit-helper commit [-t 类型] [-m 描述] [-a] [--no-review/--only-chinese/--only-english]` | | ai-review | 管理 AI 代码审查 | `git-commit-helper ai-review [--enable/--disable/--status]` | ### 提交类型 @@ -235,9 +235,11 @@ git-commit-helper commit [选项] -a, --all 自动添加所有已修改但未暂存的文件 --no-review 禁用当前提交的代码审查功能 --only-chinese 仅保留中文提交信息 + --only-english 仅保留英文提交信息 ``` 示例: + ```bash # 生成提交信息 git-commit-helper commit @@ -256,10 +258,18 @@ git-commit-helper commit --type fix --message "修复内存泄漏" -a # 设置默认使用中文 git-commit-helper config --set-only-chinese true # 默认仅使用中文 -git-commit-helper config --set-only-chinese false # 默认使用中英双语 + +# 设置默认使用英文 +git-commit-helper config --set-only-english true # 默认仅使用英文 + +# 设置默认使用中英双语 +git-commit-helper config --set-only-chinese false --set-only-english false # 默认使用中英双语 # 单次提交使用中文 git-commit-helper commit --type feat --message "添加新功能" --only-chinese + +# 单次提交使用英文 +git-commit-helper commit --type feat --message "Add new functions" --only-english ``` ### AI 代码审查功能 @@ -305,7 +315,7 @@ git-commit-helper https://gerrit.example.com/c/project/+/123456 ``` 输出格式: -``` +```txt 标题:<原始标题> 中文翻译:<标题翻译> diff --git a/src/commit.rs b/src/commit.rs index 9089cde..e29de87 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -2,6 +2,130 @@ use regex::Regex; use crate::ai_service; use crate::config; +// 语言模式枚举 +#[derive(Debug, Clone, Copy)] +enum LanguageMode { + ChineseOnly, + EnglishOnly, + Bilingual, +} + +// 提示词模板常量 +const ENGLISH_PROMPT_TEMPLATE: &str = r#"Please analyze the git diff content and generate a commit message in English only: +1. First line: type: message (under 50 characters) +2. Empty line after the title +3. Detailed explanation in English (what was changed and why) +4. Type must be one of: feat/fix/docs/style/refactor/test/chore +5. Focus on both WHAT changed and WHY it was necessary +6. Include any important technical details or context +7. DO NOT include any Chinese content +8. DO NOT wrap the response in any markdown or code block markers + +Example response format: +feat: add user authentication module + +1. Implement JWT-based authentication system +2. Add user login and registration endpoints +3. Include password hashing with bcrypt +4. Set up token refresh mechanism + +Please respond with ONLY the commit message following this format, +DO NOT end commit titles with any punctuation."#; + +const CHINESE_PROMPT_TEMPLATE: &str = r#"请分析以下 git diff 内容,并按照以下格式生成提交信息: +1. 第一行为标题:type: message(不超过50个字符) +2. 标题下方空一行 +3. 详细的中文说明(解释做了什么改动以及为什么需要这些改动) +4. type 必须是以下之一:feat/fix/docs/style/refactor/test/chore +5. 关注点:变更内容(做了什么)和变更原因(为什么) +6. 包含重要的技术细节或上下文 +7. 不要使用任何 markdown 或代码块标记 +8. 标题结尾不要使用标点符号 + +示例格式: +feat: 添加用户认证模块 + +1. 实现基于 JWT 的认证系统 +2. 添加用户登录和注册端点 +3. 包含使用 bcrypt 的密码哈希处理 +4. 设置令牌刷新机制"#; + +const BILINGUAL_PROMPT_TEMPLATE: &str = r#"Please analyze the git diff content and generate a detailed bilingual commit message with: +1. First line in English: type: message (under 50 characters) +2. Empty line after the title +3. Detailed explanation in English (what was changed and why) +4. Empty line after English explanation +5. Chinese title and explanation (translate the English content) +6. Type must be one of: feat/fix/docs/style/refactor/test/chore +7. Focus on both WHAT changed and WHY it was necessary +8. Include any important technical details or context +9. DO NOT wrap the response in any markdown or code block markers + +Example response format: +feat: add user authentication module + +1. Implement JWT-based authentication system +2. Add user login and registration endpoints +3. Include password hashing with bcrypt +4. Set up token refresh mechanism + +feat: 添加用户认证模块 + +1. 实现基于 JWT 的认证系统 +2. 添加用户登录和注册端点 +3. 包含使用 bcrypt 的密码哈希处理 +4. 设置令牌刷新机制 + +Please respond with ONLY the commit message following this format, +DO NOT end commit titles with any punctuation."#; + +impl LanguageMode { + fn determine(only_chinese: bool, only_english: bool) -> Self { + if only_english { + Self::EnglishOnly + } else if only_chinese { + Self::ChineseOnly + } else { + Self::Bilingual + } + } + + fn template(&self) -> &'static str { + match self { + Self::EnglishOnly => ENGLISH_PROMPT_TEMPLATE, + Self::ChineseOnly => CHINESE_PROMPT_TEMPLATE, + Self::Bilingual => BILINGUAL_PROMPT_TEMPLATE, + } + } +} + +// 统一的提示词构建函数 +fn build_prompt(mode: LanguageMode, user_message: Option<&str>) -> String { + let mut prompt = String::from(mode.template()); + + if let Some(msg) = user_message { + match mode { + LanguageMode::ChineseOnly => { + prompt.push_str(&format!("\n\n用户描述:\n{}\n\n变更内容:\n", msg)); + } + _ => { + prompt.push_str(&format!("\n\nUser Description:\n{}\n\nChanges:\n", msg)); + } + } + } else { + match mode { + LanguageMode::ChineseOnly => { + prompt.push_str("\n\n变更内容:\n"); + } + _ => { + prompt.push_str("\n\nHere are the changes:\n"); + } + } + } + + prompt +} + pub struct CommitMessage { pub title: String, pub body: Option, @@ -104,13 +228,23 @@ pub async fn generate_commit_message( no_review: bool, no_translate: bool, mut only_chinese: bool, + mut only_english: bool, ) -> anyhow::Result<()> { // 加载配置,如果指定了参数则使用参数值,否则使用配置中的默认值 if let Ok(config) = config::Config::load() { - if !only_chinese { + if !only_chinese && !only_english { only_chinese = config.only_chinese; + only_english = config.only_english; } } + + // 处理语言选项冲突:only_english 优先级最高 + if only_english { + only_chinese = false; + } else if only_chinese { + only_english = false; + } + // 如果指定了 -a 参数,先执行 git add -u if auto_add { info!("自动添加已修改的文件..."); @@ -146,108 +280,9 @@ pub async fn generate_commit_message( // 设置环境变量标记跳过后续的代码审查 std::env::set_var("GIT_COMMIT_HELPER_SKIP_REVIEW", "1"); - let prompt = match (message, only_chinese) { - (Some(msg), true) => format!( - "请分析以下 git diff 内容,并按照以下格式生成提交信息:\ - 1. 第一行为标题:type: message(不超过50个字符)\ - 2. 标题下方空一行\ - 3. 详细的中文说明(解释做了什么改动以及为什么需要这些改动)\ - 4. type 必须是以下之一:feat/fix/docs/style/refactor/test/chore\ - 5. 关注点:变更内容(做了什么)和变更原因(为什么)\ - 6. 包含重要的技术细节或上下文\ - 7. 不要使用任何 markdown 或代码块标记\ - 8. 标题结尾不要使用标点符号\ - \n\n示例格式:\ - feat: 添加用户认证模块\n\ - 1. 实现基于 JWT 的认证系统\n\ - 2. 添加用户登录和注册端点\n\ - 3. 包含使用 bcrypt 的密码哈希处理\n\ - 4. 设置令牌刷新机制 - \n\n用户描述:\n{}\n\n变更内容:\n", - msg - ), - (None, true) => format!( - "请分析以下 git diff 内容,并按照以下格式生成提交信息:\ - 1. 第一行为标题:type: message(不超过50个字符)\ - 2. 标题下方空一行\ - 3. 详细的中文说明(解释做了什么改动以及为什么需要这些改动)\ - 4. type 必须是以下之一:feat/fix/docs/style/refactor/test/chore\ - 5. 关注点:变更内容(做了什么)和变更原因(为什么)\ - 6. 包含重要的技术细节或上下文\ - 7. 不要使用任何 markdown 或代码块标记\ - 8. 标题结尾不要使用标点符号\ - \n\n示例格式:\ - feat: 添加用户认证模块\n\ - 1. 实现基于 JWT 的认证系统\n\ - 2. 添加用户登录和注册端点\n\ - 3. 包含使用 bcrypt 的密码哈希处理\n\ - 4. 设置令牌刷新机制 - \n\n变更内容:\n" - ), - (Some(msg), false) => format!( - "Please analyze the git diff content and generate a detailed bilingual commit message with: - 1. First line in English: type: message (under 50 characters) - 2. Empty line after the title - 3. Detailed explanation in English (what was changed and why) - 4. Empty line after English explanation - 5. Chinese title and explanation (translate the English content) - 6. Type must be one of: feat/fix/docs/style/refactor/test/chore - 7. Focus on both WHAT changed and WHY it was necessary - 8. Include any important technical details or context - 9. DO NOT wrap the response in any markdown or code block markers - - Example response format: - feat: add user authentication module - - 1. Implement JWT-based authentication system - 2. Add user login and registration endpoints - 3. Include password hashing with bcrypt - 4. Set up token refresh mechanism - - feat: 添加用户认证模块 - - 1. 实现基于 JWT 的认证系统 - 2. 添加用户登录和注册端点 - 3. 包含使用 bcrypt 的密码哈希处理 - 4. 设置令牌刷新机制 - - Please respond with ONLY the commit message following this format, - DO NOT end commit titles with any punctuation. - \n\nUser Description:\n{}\n\nChanges:\n", - msg - ), - (None, false) => format!( - "Please analyze the git diff content and generate a detailed bilingual commit message with: - 1. First line in English: type: message (under 50 characters) - 2. Empty line after the title - 3. Detailed explanation in English (what was changed and why) - 4. Empty line after English explanation - 5. Chinese title and explanation (translate the English content) - 6. Type must be one of: feat/fix/docs/style/refactor/test/chore - 7. Focus on both WHAT changed and WHY it was necessary - 8. Include any important technical details or context - 9. DO NOT wrap the response in any markdown or code block markers - - Example response format: - feat: add user authentication module - - 1. Implement JWT-based authentication system - 2. Add user login and registration endpoints - 3. Include password hashing with bcrypt - 4. Set up token refresh mechanism - - feat: 添加用户认证模块 - - 1. 实现基于 JWT 的认证系统 - 2. 添加用户登录和注册端点 - 3. 包含使用 bcrypt 的密码哈希处理 - 4. 设置令牌刷新机制 - - Please respond with ONLY the commit message following this format, - DO NOT end commit titles with any punctuation. - \n\nHere are the changes:\n" - ) - }; + // 确定语言模式并构建提示词 + let language_mode = LanguageMode::determine(only_chinese, only_english); + let prompt = build_prompt(language_mode, message.as_deref()); debug!("生成的提示信息:\n{}", prompt); diff --git a/src/config.rs b/src/config.rs index a872a92..304b144 100644 --- a/src/config.rs +++ b/src/config.rs @@ -24,6 +24,8 @@ pub struct Config { pub gerrit: Option, // Gerrit 配置 #[serde(default = "default_only_chinese")] pub only_chinese: bool, // 是否默认只使用中文 + #[serde(default = "default_only_english")] + pub only_english: bool, // 是否默认只使用英文 } // 添加默认值函数 @@ -31,6 +33,10 @@ fn default_only_chinese() -> bool { false } +fn default_only_english() -> bool { + false +} + #[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct GerritConfig { pub username: Option, @@ -82,6 +88,7 @@ impl Config { max_tokens: default_max_tokens(), gerrit: None, only_chinese: false, // 默认关闭 + only_english: false, // 默认关闭 } } @@ -279,6 +286,7 @@ impl Config { max_tokens: default_max_tokens(), gerrit: None, only_chinese: false, // 默认关闭 + only_english: false, // 默认关闭 }; // 确保配置目录存在 @@ -307,6 +315,7 @@ impl Config { max_tokens: config.max_tokens, gerrit: None, only_chinese: false, + only_english: false, }; let translator = ai_service::create_translator(&test_config).await?; match translator.translate("这是一个测试消息,用于验证翻译功能是否正常。").await { @@ -480,6 +489,7 @@ impl Config { max_tokens: self.max_tokens, gerrit: None, only_chinese: false, + only_english: false, }; let translator = ai_service::create_translator(&test_config).await?; let text = "这是一个测试消息,用于验证翻译功能是否正常。"; diff --git a/src/main.rs b/src/main.rs index b64ec63..db5c96b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,6 +39,9 @@ enum Commands { /// 设置默认是否只使用中文提交信息,true: 仅中文,false: 中英双语 #[arg(long = "set-only-chinese", help = "设置是否默认只使用中文提交信息,true: 仅中文,false: 中英双语")] only_chinese: Option, + /// 设置默认是否只使用英文提交信息,true: 仅英文,false: 中英双语 + #[arg(long = "set-only-english", help = "设置是否默认只使用英文提交信息,true: 仅英文,false: 中英双语")] + only_english: Option, }, /// 显示当前配置信息 Show, @@ -86,6 +89,9 @@ enum Commands { /// 仅保留中文提交信息 #[arg(long = "only-chinese")] only_chinese: bool, + /// 仅保留英文提交信息 + #[arg(long = "only-english")] + only_english: bool, }, /// 管理 AI 代码审查功能 #[command(name = "ai-review")] @@ -187,13 +193,38 @@ async fn main() -> Result<()> { }; match cli.command { - Some(Commands::Config { only_chinese }) => { + Some(Commands::Config { only_chinese, only_english }) => { if let Some(only_chinese) = only_chinese { let mut config = config::Config::load().unwrap_or_else(|_| config::Config::new()); config.only_chinese = only_chinese; + if only_chinese { + config.only_english = false; // 如果设置为仅中文,则清除仅英文标志 + } + config.save()?; + let language_mode = if config.only_chinese { + "仅中文" + } else if config.only_english { + "仅英文" + } else { + "中英双语" + }; + println!("{}", Style::green(&format!("已将默认提交信息语言设置为: {}", language_mode))); + Ok(()) + } else if let Some(only_english) = only_english { + let mut config = config::Config::load().unwrap_or_else(|_| config::Config::new()); + config.only_english = only_english; + if only_english { + config.only_chinese = false; // 如果设置为仅英文,则清除仅中文标志 + } config.save()?; - println!("{}", Style::green(&format!("已将默认提交信息语言设置为: {}", - if only_chinese { "仅中文" } else { "中英双语" }))); + let language_mode = if config.only_chinese { + "仅中文" + } else if config.only_english { + "仅英文" + } else { + "中英双语" + }; + println!("{}", Style::green(&format!("已将默认提交信息语言设置为: {}", language_mode))); Ok(()) } else { config::Config::interactive_config().await?; @@ -373,14 +404,21 @@ async fn main() -> Result<()> { Err(e) => Err(e) } } - Some(Commands::Commit { r#type, message, all, no_translate, only_chinese }) => { - commit::generate_commit_message(r#type, message, all, cli.no_review, no_translate, only_chinese).await + Some(Commands::Commit { r#type, message, all, no_translate, only_chinese, only_english }) => { + commit::generate_commit_message(r#type, message, all, cli.no_review, no_translate, only_chinese, only_english).await } Some(Commands::AIReview { enable, disable, status }) => { let mut config = config::Config::load()?; if status { + let language_mode = if config.only_chinese { + "仅中文" + } else if config.only_english { + "仅英文" + } else { + "中英双语" + }; println!("{}", Style::title(&format!("AI 代码审查功能当前状态: {}", if config.ai_review { "已启用" } else { "已禁用" }))); - println!("{}", Style::plain(&format!("默认提交信息语言: {}", if config.only_chinese { "仅中文" } else { "中英双语" }))); + println!("{}", Style::plain(&format!("默认提交信息语言: {}", language_mode))); return Ok(()); } if enable {