From d99ce60122b72fd6f12b70da2f1140c24bbafad8 Mon Sep 17 00:00:00 2001 From: Yuya Fujiwara Date: Mon, 13 Apr 2026 10:46:24 +0900 Subject: [PATCH] refactor(internal/app): strip ANSI escape sequences from commit messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a regular expression to remove ANSI escape sequences from commit messag messages, ensuring that sanitized messages are clean and free of color code codes or cursor movements. This improves readability and consistency in log log output. - Added `regexp.MustCompile` for matching and removing ANSI escape sequence sequences. - Updated `sanitizeMessage` function to include the new regex logic. - Created a test function `TestSanitizeMessageStripANSIEscapeSequences` to  validate the functionality with various scenarios, including cursor backspa backspace, SGR color codes, and messages without any escape sequences. --- internal/app/app.go | 6 +++++- internal/app/app_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/internal/app/app.go b/internal/app/app.go index ad43581..d74459f 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "os" + "regexp" "strings" "git-ai-commit/internal/config" @@ -124,8 +125,11 @@ func selectEngine(cfg config.Config) (engine.Engine, string, error) { return engine.CLI{Command: name, Args: nil}, name, nil } +var ansiEscapeRe = regexp.MustCompile(`\x1b\[[0-9;]*[A-Za-z]`) + func sanitizeMessage(message string) string { - clean := strings.TrimSpace(message) + clean := ansiEscapeRe.ReplaceAllString(message, "") + clean = strings.TrimSpace(clean) if clean == "" { return "" } diff --git a/internal/app/app_test.go b/internal/app/app_test.go index 5e58760..af5b1f8 100644 --- a/internal/app/app_test.go +++ b/internal/app/app_test.go @@ -188,6 +188,44 @@ func TestSelectEngineCustomArgs(t *testing.T) { } } +func TestSanitizeMessageStripANSIEscapeSequences(t *testing.T) { + tests := []struct { + name string + input string + want string + }{ + { + name: "cursor back and erase", + input: "Add uni\x1b[3D\x1b[Kntended behavior fix", + want: "Add unintended behavior fix", + }, + { + name: "multiple ANSI sequences", + input: "Fix \x1b[8D\x1b[K\x1b[4D\x1b[Kbug in parser", + want: "Fix bug in parser", + }, + { + name: "SGR color codes", + input: "\x1b[32mAdd feature\x1b[0m", + want: "Add feature", + }, + { + name: "no ANSI sequences", + input: "Clean commit message", + want: "Clean commit message", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := sanitizeMessage(tt.input) + if got != tt.want { + t.Fatalf("sanitizeMessage(%q) = %q, want %q", tt.input, got, tt.want) + } + }) + } +} + func TestSanitizeMessageCodeFence(t *testing.T) { input := "```\nfeat: add thing\n```" got := sanitizeMessage(input)