Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
tags:
- 'v*'
workflow_dispatch:


jobs:
build:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/target
.codebuddy/
18 changes: 18 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-toml
- id: check-merge-conflict
- id: check-added-large-files
- repo: https://github.com/doublify/pre-commit-rust
rev: v1.0
hooks:
- id: fmt
args: ["--all", "--", "--check"]
- id: clippy
args: ["--all-targets", "--all-features", "--", "-D", "warnings"]
- id: cargo-check
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,29 @@ NOTE: All common config can be configured via `~/.fastcommit/config.toml`
fastcommit -c --commit-args "-s" --commit-args "--no-verify"
```

## Development

### Pre-commit Hooks

This project uses [pre-commit](https://pre-commit.com/) to run code quality checks before each commit.

```bash
# Install pre-commit
pip install pre-commit

# Install the git hooks
pre-commit install

# (Optional) Run all hooks manually
pre-commit run --all-files
```

The following checks will run automatically on `git commit`:

- **rustfmt** — Code formatting check
- **clippy** — Static analysis with warnings as errors
- **cargo-check** — Compilation check

## GitHub PR Integration

`fastcommit` can generate commit messages for GitHub Pull Requests, which is useful when merging PRs.
Expand Down
23 changes: 23 additions & 0 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,29 @@ fastcommit pr 123 -l zh

更多详情请参阅 [GitHub PR 集成指南](docs/github-pr-integration.md)。

## 开发

### Pre-commit Hooks

本项目使用 [pre-commit](https://pre-commit.com/) 在每次提交前自动运行代码质量检查。

```bash
# 安装 pre-commit
pip install pre-commit

# 安装 git hooks
pre-commit install

# (可选)手动运行所有检查
pre-commit run --all-files
```

以下检查会在 `git commit` 时自动执行:

- **rustfmt** — 代码格式化检查
- **clippy** — 静态分析,警告视为错误
- **cargo-check** — 编译检查

## 贡献

欢迎贡献代码或提出建议!请先阅读 [贡献指南](CONTRIBUTING.md)。
Expand Down
2 changes: 1 addition & 1 deletion docs/TEXT_WRAPPING.md
Original file line number Diff line number Diff line change
Expand Up @@ -420,4 +420,4 @@ Contributions are welcome! Please refer to:

## License

This feature follows the project's MIT license.
This feature follows the project's MIT license.
22 changes: 6 additions & 16 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,15 @@ impl Config {
let api_base = if api_base.ends_with("/") {
api_base.to_owned()
} else {
format!("{}/", api_base)
format!("{api_base}/")
};

api_base
}
}

/// Commit message verbosity level.
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Copy, clap::ValueEnum)]
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Copy, clap::ValueEnum, Default)]
pub enum Verbosity {
/// Detailed commit message.
#[serde(rename = "verbose")]
Expand All @@ -123,17 +123,12 @@ pub enum Verbosity {
/// Quiet commit message.
#[serde(rename = "quiet")]
#[clap(name = "quiet")]
#[default]
Quiet,
}

impl Default for Verbosity {
fn default() -> Self {
Verbosity::Quiet
}
}

impl Verbosity {
pub fn to_template_level(&self) -> &'static str {
pub fn as_template_level(self) -> &'static str {
match self {
Verbosity::Verbose => "详细",
Verbosity::Normal => "中等",
Expand All @@ -142,22 +137,17 @@ impl Verbosity {
}
}

#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, clap::ValueEnum)]
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, clap::ValueEnum, Default)]
pub enum CommitLanguage {
#[clap(name = "en")]
#[serde(rename = "en")]
English,
#[clap(name = "zh")]
#[serde(rename = "zh")]
#[default]
Chinese,
}

impl Default for CommitLanguage {
fn default() -> Self {
CommitLanguage::Chinese
}
}

impl Display for CommitLanguage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Expand Down
15 changes: 5 additions & 10 deletions src/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub async fn generate_commit_message(
if desc.trim().is_empty() {
desc
} else {
format!("commit message: {}", desc)
format!("commit message: {desc}")
}
});

Expand Down Expand Up @@ -91,22 +91,17 @@ fn delete_thinking_contents(orig: &str) -> String {
let end_tag = "</think>";

let start_idx = orig.find(start_tag).unwrap_or(orig.len());
let end_idx = orig.find(end_tag).unwrap_or_else(|| 0);
let s = if start_idx < end_idx {
let end_idx = orig.find(end_tag).unwrap_or(0);
if start_idx < end_idx {
let mut result = orig[..start_idx].to_string();
result.push_str(&orig[end_idx..]);
log::debug!(
"Delete thinking contents, start_idx: {}, end_idx: {}: {:?} => {:?}",
start_idx,
end_idx,
orig,
result
"Delete thinking contents, start_idx: {start_idx}, end_idx: {end_idx}: {orig:?} => {result:?}"
);
result
} else {
orig.to_string()
};
s
}
}

fn extract_aicommit_message(response: &str) -> anyhow::Result<String> {
Expand Down
8 changes: 3 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,10 @@ fn print_wrapped_content(wrapper: &Option<TextWrapper>, content: &str, prefix: O
} else {
println!("{}", wrapper.wrap(content));
}
} else if let Some(p) = prefix {
println!("{p} {content}");
} else {
if let Some(p) = prefix {
println!("{} {}", p, content);
} else {
println!("{}", content);
}
println!("{content}");
}
}

Expand Down
32 changes: 12 additions & 20 deletions src/sanitizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,31 +76,23 @@ pub fn sanitize(

// Apply builtin patterns
for (kind, re) in builtin.iter() {
loop {
if let Some(m) = re.find(&sanitized) {
counter += 1;
let placeholder = format!("[REDACTED:{}#{}]", kind, counter);
sanitized.replace_range(m.start()..m.end(), &placeholder);
redactions.push(Redaction::new(kind, placeholder));
} else {
break;
}
while let Some(m) = re.find(&sanitized) {
counter += 1;
let placeholder = format!("[REDACTED:{kind}#{counter}]");
sanitized.replace_range(m.start()..m.end(), &placeholder);
redactions.push(Redaction::new(kind, placeholder));
}
}

// Apply custom patterns – use their provided name (converted to static via leak for simplicity)
for meta in custom_patterns {
loop {
if let Some(m) = meta.regex.find(&sanitized) {
counter += 1;
let placeholder = format!("[REDACTED:{}#{}]", meta.name, counter);
sanitized.replace_range(m.start()..m.end(), &placeholder);
// We leak the string to get a 'static str; acceptable given tiny count and CLI nature
let leaked: &'static str = Box::leak(meta.name.clone().into_boxed_str());
redactions.push(Redaction::new(leaked, placeholder));
} else {
break;
}
while let Some(m) = meta.regex.find(&sanitized) {
counter += 1;
let placeholder = format!("[REDACTED:{}#{counter}]", meta.name);
sanitized.replace_range(m.start()..m.end(), &placeholder);
// We leak the string to get a 'static str; acceptable given tiny count and CLI nature
let leaked: &'static str = Box::leak(meta.name.clone().into_boxed_str());
redactions.push(Redaction::new(leaked, placeholder));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/template_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub fn render_template(template: &str, context: TemplateContext) -> anyhow::Resu
)
.replace(
PromptTemplateReplaceLabel::VerbosityLevel.get_label(),
context.verbosity.to_template_level(),
context.verbosity.as_template_level(),
)
.replace(
PromptTemplateReplaceLabel::Diff.get_label(),
Expand Down
4 changes: 2 additions & 2 deletions src/text_wrapper/hybrid_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,14 +250,14 @@ impl HybridWrapper {
}
TextSegment::CodeBlock(code) => {
if config.handle_code_blocks {
format!("\n{}\n", code)
format!("\n{code}\n")
} else {
code.clone()
}
}
TextSegment::Link(url, text) => {
if config.preserve_links {
format!("[{}]({})", text, url)
format!("[{text}]({url})")
} else {
text.clone()
}
Expand Down
Loading