git_auto 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +113 -0
- data/exe/git_auto +7 -0
- data/lib/git_auto/cli.rb +79 -0
- data/lib/git_auto/commands/commit_message_command.rb +315 -0
- data/lib/git_auto/commands/config_command.rb +175 -0
- data/lib/git_auto/commands/history_analysis_command.rb +87 -0
- data/lib/git_auto/commands/setup_command.rb +113 -0
- data/lib/git_auto/config/credential_store.rb +73 -0
- data/lib/git_auto/config/settings.rb +95 -0
- data/lib/git_auto/errors.rb +12 -0
- data/lib/git_auto/formatters/diff_formatter.rb +49 -0
- data/lib/git_auto/formatters/diff_summarizer.rb +99 -0
- data/lib/git_auto/formatters/message_formatter.rb +53 -0
- data/lib/git_auto/services/ai_service.rb +395 -0
- data/lib/git_auto/services/git_service.rb +115 -0
- data/lib/git_auto/services/history_service.rb +150 -0
- data/lib/git_auto/validators/commit_message_validator.rb +89 -0
- data/lib/git_auto/version.rb +5 -0
- data/lib/git_auto.rb +52 -0
- metadata +268 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 18b1522d4ba03cddfe1536bb6ee06cab7b12c7b3368c1883ebda20825c89673f
|
4
|
+
data.tar.gz: 62e9d5d3a7f0b89292ed993ab601a63fa91134abb49ecda8bbbc349384a3aff8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e3ee6ea8c6e9de921c13bb63b0c5d0e9232754b3cca4c39d1bc2de4b6cabb54ad1f0800ced7cafbaa60a13f22d5b5cd0ebff85541912c5b7dd670fd8d0982f86
|
7
|
+
data.tar.gz: a9f369e2008ed297e21fa88f049ba36ed3446ad72ecdc845537bcd20529c947bc31df69fc7195b554ff7b094ce139ff8717735b9b3b5124099ab86292b3a7bce
|
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2024 Guillermo Diaz
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# GitAuto š¤āØ
|
2
|
+
|
3
|
+
> AI-powered commit messages that make sense
|
4
|
+
|
5
|
+
GitAuto is a Ruby gem that streamlines your git workflow by automatically generating meaningful commit messages using AI. Say goodbye to generic commit messages and hello to clear, consistent, and informative descriptions of your changes.
|
6
|
+
|
7
|
+
## Features š
|
8
|
+
|
9
|
+
- šÆ **Intelligent Analysis**: Automatically analyzes your staged changes
|
10
|
+
- š” **Smart Generation**: Creates conventional commit messages that actually make sense
|
11
|
+
- šØ **Beautiful CLI**: Interactive and colorful command-line interface
|
12
|
+
- š **Clipboard Integration**: Easy copying of generated messages
|
13
|
+
- š **Diff Preview**: Optional preview of changes before message generation
|
14
|
+
- š **Message History**: Keeps track of your commit messages
|
15
|
+
- š¤ **AI Providers**: Supports multiple AI providers:
|
16
|
+
- OpenAI (GPT-4o, GPT-4o mini)
|
17
|
+
- Anthropic (Claude 3.5 Sonnet, Claude 3.5 Haiku)
|
18
|
+
- š **Secure Storage**: Your API keys are encrypted using AES-256-CBC and stored securely
|
19
|
+
|
20
|
+
## Installation š
|
21
|
+
|
22
|
+
```bash
|
23
|
+
gem install git_auto
|
24
|
+
```
|
25
|
+
|
26
|
+
Or add to your Gemfile:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
gem 'git_auto'
|
30
|
+
```
|
31
|
+
|
32
|
+
## Usage š ļø
|
33
|
+
|
34
|
+
1. Stage your changes as usual:
|
35
|
+
```bash
|
36
|
+
git add .
|
37
|
+
```
|
38
|
+
|
39
|
+
2. Generate a commit message:
|
40
|
+
```bash
|
41
|
+
git-auto commit
|
42
|
+
```
|
43
|
+
|
44
|
+
3. Review, edit if needed, and confirm!
|
45
|
+
|
46
|
+
## Setup and Configuration š§
|
47
|
+
|
48
|
+
### Initial Setup
|
49
|
+
|
50
|
+
Run the setup wizard to configure GitAuto:
|
51
|
+
```bash
|
52
|
+
git-auto setup
|
53
|
+
```
|
54
|
+
This will guide you through:
|
55
|
+
- Setting up your preferred AI provider
|
56
|
+
- Configuring your API keys (stored securely with AES-256-CBC encryption)
|
57
|
+
- Setting default preferences
|
58
|
+
|
59
|
+
### Configuration Management
|
60
|
+
|
61
|
+
Manage your settings anytime with:
|
62
|
+
```bash
|
63
|
+
git-auto config
|
64
|
+
```
|
65
|
+
|
66
|
+
This allows you to:
|
67
|
+
- Update API keys
|
68
|
+
- Change AI provider settings
|
69
|
+
- Modify default behaviors
|
70
|
+
- View current configuration
|
71
|
+
|
72
|
+
### Security š
|
73
|
+
|
74
|
+
GitAuto takes security seriously:
|
75
|
+
- API keys are encrypted using AES-256-CBC encryption
|
76
|
+
- Keys are stored in your system's user directory (`~/.git_auto/credentials.yml`)
|
77
|
+
- You can set a custom encryption key via `GIT_AUTO_SECRET` environment variable
|
78
|
+
|
79
|
+
### Environment Variables
|
80
|
+
|
81
|
+
GitAuto can also be configured through environment variables:
|
82
|
+
|
83
|
+
- `OPENAI_API_KEY`: Your OpenAI API key for message generation
|
84
|
+
- `GIT_AUTO_MODEL`: OpenAI model to use (default: gpt-3.5-turbo)
|
85
|
+
- `GIT_AUTO_SECRET`: Custom encryption key for storing API keys (optional)
|
86
|
+
|
87
|
+
## Requirements āļø
|
88
|
+
|
89
|
+
- Ruby >= 3.0.0
|
90
|
+
- Git repository with staged changes
|
91
|
+
|
92
|
+
## Screenshots šø
|
93
|
+
|
94
|
+
*Coming soon...*
|
95
|
+
|
96
|
+
## Roadmap šŗļø
|
97
|
+
|
98
|
+
Here's what we're planning for future releases:
|
99
|
+
|
100
|
+
- š¤ Support for Google Gemini AI
|
101
|
+
- š Automatic PR description generation
|
102
|
+
- More exciting features coming soon!
|
103
|
+
|
104
|
+
## Contributing š¤
|
105
|
+
|
106
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/diazgdev/git_auto.
|
107
|
+
|
108
|
+
## License š
|
109
|
+
|
110
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
111
|
+
|
112
|
+
---
|
113
|
+
Made with ā¤ļø by [Guillermo Diaz](https://github.com/diazgdev)
|
data/exe/git_auto
ADDED
data/lib/git_auto/cli.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thor"
|
4
|
+
require "tty-prompt"
|
5
|
+
require "colorize"
|
6
|
+
|
7
|
+
module GitAuto
|
8
|
+
class CLI < Thor
|
9
|
+
def self.exit_on_failure?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
# Add version information
|
14
|
+
map ["--version", "-v"] => :version
|
15
|
+
desc "--version, -v", "Print version"
|
16
|
+
def version
|
17
|
+
puts "git_auto version #{GitAuto::VERSION}"
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "setup", "Configure GitAuto settings and API keys"
|
21
|
+
long_desc <<-LONGDESC
|
22
|
+
Interactive setup wizard for GitAuto.
|
23
|
+
|
24
|
+
This will guide you through:
|
25
|
+
* Selecting an AI provider (Claude or OpenAI)
|
26
|
+
* Configuring your API key
|
27
|
+
* Setting commit message preferences
|
28
|
+
* Configuring other options
|
29
|
+
LONGDESC
|
30
|
+
def setup
|
31
|
+
Commands::SetupCommand.new.execute
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "config [get|set] [key] [value]", "View or update configuration"
|
35
|
+
long_desc <<-LONGDESC
|
36
|
+
Manage GitAuto configuration.
|
37
|
+
|
38
|
+
Examples:
|
39
|
+
git_auto config # Interactive configuration
|
40
|
+
git_auto config get # Show all settings
|
41
|
+
git_auto config get ai_provider # Show specific setting
|
42
|
+
git_auto config set ai_model gpt-4 # Update specific setting
|
43
|
+
LONGDESC
|
44
|
+
def config(*args)
|
45
|
+
Commands::ConfigCommand.new.execute(args)
|
46
|
+
end
|
47
|
+
|
48
|
+
desc "commit", "Generate AI-powered commit message"
|
49
|
+
method_option :style, type: :string, desc: "Commit message style (conventional, simple, detailed)"
|
50
|
+
method_option :scope, type: :string, desc: "Commit scope for conventional style"
|
51
|
+
method_option :preview, type: :boolean, desc: "Show diff preview before committing"
|
52
|
+
long_desc <<-LONGDESC
|
53
|
+
Generate an AI-powered commit message for your staged changes.
|
54
|
+
|
55
|
+
Examples:
|
56
|
+
git_auto commit # Use default style
|
57
|
+
git_auto commit --style simple # Use simple style
|
58
|
+
git_auto commit --style conventional --scope api # Specify scope
|
59
|
+
LONGDESC
|
60
|
+
def commit
|
61
|
+
Commands::CommitMessageCommand.new(options).execute
|
62
|
+
end
|
63
|
+
|
64
|
+
desc "analyze", "Analyze commit history patterns"
|
65
|
+
method_option :limit, type: :numeric, default: 10, desc: "Number of commits to analyze"
|
66
|
+
method_option :save, type: :boolean, desc: "Save patterns for future commits"
|
67
|
+
long_desc <<-LONGDESC
|
68
|
+
Analyze your repository's commit history to learn patterns and improve future commit messages.
|
69
|
+
|
70
|
+
Examples:
|
71
|
+
git_auto analyze # Analyze last 10 commits
|
72
|
+
git_auto analyze --limit 50 # Analyze last 50 commits
|
73
|
+
git_auto analyze --save # Save patterns for future use
|
74
|
+
LONGDESC
|
75
|
+
def analyze
|
76
|
+
Commands::HistoryAnalysisCommand.new(options).execute
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,315 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "tty-prompt"
|
4
|
+
require "tty-spinner"
|
5
|
+
require "colorize"
|
6
|
+
require "clipboard"
|
7
|
+
require_relative "../formatters/diff_formatter"
|
8
|
+
require_relative "../formatters/message_formatter"
|
9
|
+
require_relative "../validators/commit_message_validator"
|
10
|
+
|
11
|
+
module GitAuto
|
12
|
+
module Commands
|
13
|
+
class CommitMessageCommand
|
14
|
+
def initialize(options = {})
|
15
|
+
@options = options.dup
|
16
|
+
@prompt = TTY::Prompt.new
|
17
|
+
@spinner = TTY::Spinner.new("[:spinner] :message...")
|
18
|
+
@settings = Config::Settings.new
|
19
|
+
@git_service = Services::GitService.new
|
20
|
+
@ai_service = Services::AIService.new(@settings)
|
21
|
+
@history_service = Services::HistoryService.new
|
22
|
+
@retry_count = 0
|
23
|
+
end
|
24
|
+
|
25
|
+
def execute
|
26
|
+
# Get repository status
|
27
|
+
status = @git_service.repository_status
|
28
|
+
validate_repository(status)
|
29
|
+
|
30
|
+
# Get and validate changes
|
31
|
+
diff = @git_service.get_staged_diff
|
32
|
+
validate_changes(diff)
|
33
|
+
|
34
|
+
# Show diff preview if requested
|
35
|
+
show_diff_preview(diff) if show_preview?
|
36
|
+
|
37
|
+
# Generate commit message
|
38
|
+
message = generate_commit_message(diff)
|
39
|
+
|
40
|
+
# Handle the generated message
|
41
|
+
handle_message(message, diff)
|
42
|
+
rescue StandardError => e
|
43
|
+
puts "\nā Error: #{e.message}".red
|
44
|
+
exit 1
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# Repository and Change Validation Methods
|
50
|
+
def validate_repository(status)
|
51
|
+
return if status[:is_clean] || status[:has_staged_changes]
|
52
|
+
|
53
|
+
puts "ā¹ļø Status:".blue
|
54
|
+
puts " Branch: #{status[:branch]}"
|
55
|
+
puts " Staged files: #{status[:staged_files].join(", ")}"
|
56
|
+
puts "\nā No changes staged for commit. Use 'git add' to stage changes.".red
|
57
|
+
exit 1
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate_changes(diff)
|
61
|
+
return unless diff.empty?
|
62
|
+
|
63
|
+
puts "ā No staged changes found. Use 'git add' first.".red
|
64
|
+
exit 1
|
65
|
+
end
|
66
|
+
|
67
|
+
# Preview Methods
|
68
|
+
def show_preview?
|
69
|
+
@options[:preview] || @settings.get(:show_diff)
|
70
|
+
end
|
71
|
+
|
72
|
+
def show_diff_preview(diff)
|
73
|
+
puts "\nš Changes to be committed:".blue
|
74
|
+
puts Formatters::DiffFormatter.new.format(diff)
|
75
|
+
|
76
|
+
return if @prompt.yes?("Continue with these changes?")
|
77
|
+
|
78
|
+
puts "Operation cancelled.".yellow
|
79
|
+
exit 0
|
80
|
+
end
|
81
|
+
|
82
|
+
# Message Generation Methods
|
83
|
+
def generate_commit_message(diff, options = @options)
|
84
|
+
style = get_commit_style
|
85
|
+
scope = options[:scope]
|
86
|
+
|
87
|
+
if style == "conventional" && scope.nil?
|
88
|
+
# Show recent scopes for reference
|
89
|
+
patterns = @history_service.analyze_patterns(20)
|
90
|
+
if patterns && patterns[:scopes]&.any?
|
91
|
+
puts "\nš Recently used scopes:".blue
|
92
|
+
patterns[:scopes].each do |scope, count|
|
93
|
+
puts " #{scope}: #{count} times"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
generate_message_with_style(diff, style, nil)
|
98
|
+
|
99
|
+
else
|
100
|
+
generate_message_with_style(diff, style, scope)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def get_commit_style
|
105
|
+
@options[:style] || @settings.get(:commit_style)
|
106
|
+
end
|
107
|
+
|
108
|
+
def generate_message_with_style(diff, style, scope)
|
109
|
+
@spinner.update(message: "Generating commit message...")
|
110
|
+
@spinner.auto_spin
|
111
|
+
message = @ai_service.generate_commit_message(diff, style: style, scope: scope)
|
112
|
+
@spinner.success("ā Message generated".green)
|
113
|
+
message
|
114
|
+
end
|
115
|
+
|
116
|
+
# Message Handling Methods
|
117
|
+
def handle_message(message, diff)
|
118
|
+
formatted = Formatters::MessageFormatter.new.format(message)
|
119
|
+
validation = validate_message(message)
|
120
|
+
display_message_and_validation(formatted, validation)
|
121
|
+
|
122
|
+
loop do
|
123
|
+
choice = prompt_user_action
|
124
|
+
break if handle_user_choice(choice, message, diff, validation)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def validate_message(message)
|
129
|
+
validator = Validators::CommitMessageValidator.new
|
130
|
+
validator.validate(message)
|
131
|
+
end
|
132
|
+
|
133
|
+
def display_message_and_validation(formatted_message, validation)
|
134
|
+
puts "\nš Generated commit message:".blue
|
135
|
+
puts formatted_message
|
136
|
+
|
137
|
+
display_validation_errors(validation[:errors]) if validation[:errors].any?
|
138
|
+
|
139
|
+
return unless validation[:warnings].any?
|
140
|
+
|
141
|
+
display_validation_warnings(validation[:warnings])
|
142
|
+
end
|
143
|
+
|
144
|
+
def display_validation_errors(errors)
|
145
|
+
puts "\nā Validation errors:".red
|
146
|
+
validator = Validators::CommitMessageValidator.new
|
147
|
+
errors.each { |error| puts validator.format_error(error) }
|
148
|
+
puts "\nPlease edit the message to fix these errors.".yellow
|
149
|
+
end
|
150
|
+
|
151
|
+
def display_validation_warnings(warnings)
|
152
|
+
puts "\nā ļø Suggestions:".yellow
|
153
|
+
validator = Validators::CommitMessageValidator.new
|
154
|
+
warnings.each { |warning| puts validator.format_warning(warning) }
|
155
|
+
end
|
156
|
+
|
157
|
+
def prompt_user_action
|
158
|
+
@prompt.select("Choose an action:", {
|
159
|
+
"ā
Accept and commit" => :accept,
|
160
|
+
"āļø Edit message" => :edit,
|
161
|
+
"š Copy to clipboard" => :copy,
|
162
|
+
"š Show diff" => :diff,
|
163
|
+
"š Show patterns" => :patterns,
|
164
|
+
"š Generate new message" => :retry,
|
165
|
+
"ā Cancel" => :cancel
|
166
|
+
})
|
167
|
+
end
|
168
|
+
|
169
|
+
# User Action Handling Methods
|
170
|
+
def handle_user_choice(choice, message, diff, validation)
|
171
|
+
case choice
|
172
|
+
when :accept
|
173
|
+
handle_accept_action(message, diff, validation)
|
174
|
+
when :edit
|
175
|
+
handle_edit_action(message)
|
176
|
+
false
|
177
|
+
when :copy
|
178
|
+
handle_copy_action(message)
|
179
|
+
false
|
180
|
+
when :diff
|
181
|
+
show_diff_preview(diff)
|
182
|
+
false
|
183
|
+
when :patterns
|
184
|
+
show_commit_patterns
|
185
|
+
false
|
186
|
+
when :retry
|
187
|
+
handle_retry_action(diff)
|
188
|
+
false
|
189
|
+
when :cancel
|
190
|
+
cancel_operation
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def handle_accept_action(message, diff, validation)
|
195
|
+
if validation[:errors].any?
|
196
|
+
puts "\nā Cannot commit: Please fix validation errors first.".red
|
197
|
+
new_message = edit_message(message)
|
198
|
+
handle_message(new_message, diff)
|
199
|
+
return true
|
200
|
+
end
|
201
|
+
accept_message(message, diff)
|
202
|
+
true
|
203
|
+
end
|
204
|
+
|
205
|
+
def handle_edit_action(message)
|
206
|
+
new_message = edit_message(message)
|
207
|
+
puts "\nš Updated message:".blue
|
208
|
+
puts Formatters::MessageFormatter.new.format(new_message)
|
209
|
+
end
|
210
|
+
|
211
|
+
def handle_copy_action(message)
|
212
|
+
Clipboard.copy(message)
|
213
|
+
puts "ā Copied to clipboard".green
|
214
|
+
end
|
215
|
+
|
216
|
+
def handle_retry_action(diff)
|
217
|
+
@retry_count += 1
|
218
|
+
|
219
|
+
# Create a new options hash for this retry
|
220
|
+
retry_options = @options.transform_keys(&:to_s)
|
221
|
+
retry_options["creativity"] = [(retry_options["creativity"].to_f + 0.1), 1.0].min if retry_options["creativity"]
|
222
|
+
retry_options["retry_attempt"] = @retry_count
|
223
|
+
|
224
|
+
new_message = generate_commit_message(diff, retry_options)
|
225
|
+
puts "\nš New message (Attempt #{@retry_count}):".blue
|
226
|
+
formatted = Formatters::MessageFormatter.new.format(new_message)
|
227
|
+
puts formatted
|
228
|
+
|
229
|
+
# Validate the message
|
230
|
+
validation = validate_message(new_message)
|
231
|
+
display_message_and_validation(formatted, validation) if validation[:errors].any? || validation[:warnings].any?
|
232
|
+
|
233
|
+
handle_message(new_message, diff)
|
234
|
+
end
|
235
|
+
|
236
|
+
# Pattern Analysis Methods
|
237
|
+
def show_commit_patterns
|
238
|
+
puts "\nš Analyzing commit patterns...".blue
|
239
|
+
patterns = @history_service.analyze_patterns
|
240
|
+
return unless patterns
|
241
|
+
|
242
|
+
display_pattern_section(patterns[:styles], "Commit Styles")
|
243
|
+
display_pattern_section(patterns[:types], "Common Types")
|
244
|
+
display_pattern_section(patterns[:scopes], "Frequent Scopes", count_format: true)
|
245
|
+
display_pattern_section(patterns[:common_phrases], "Common Phrases", count_format: true)
|
246
|
+
|
247
|
+
wait_for_user_input
|
248
|
+
end
|
249
|
+
|
250
|
+
def display_pattern_section(data, title, count_format: false)
|
251
|
+
return unless data&.any?
|
252
|
+
|
253
|
+
puts "\n#{title}:".cyan
|
254
|
+
display_pattern_items(data, count_format)
|
255
|
+
end
|
256
|
+
|
257
|
+
def display_pattern_items(items, count_format)
|
258
|
+
items.each do |key, value|
|
259
|
+
formatted_value = format_pattern_value(value, count_format)
|
260
|
+
puts " #{key}: #{formatted_value}"
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
def format_pattern_value(value, count_format)
|
265
|
+
if count_format
|
266
|
+
"#{value} times"
|
267
|
+
else
|
268
|
+
"#{value}%"
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def wait_for_user_input
|
273
|
+
puts "\nPress any key to continue..."
|
274
|
+
@prompt.keypress
|
275
|
+
end
|
276
|
+
|
277
|
+
# Utility Methods
|
278
|
+
def edit_message(message)
|
279
|
+
puts "\nEdit your commit message:"
|
280
|
+
puts "Enter your commit message (press Ctrl+D or Ctrl+Z to finish)".light_black
|
281
|
+
editor_input = $stdin.gets
|
282
|
+
editor_input&.strip || message
|
283
|
+
end
|
284
|
+
|
285
|
+
def accept_message(message, diff)
|
286
|
+
@spinner.update(message: "Creating commit...")
|
287
|
+
@spinner.auto_spin
|
288
|
+
# Ensure we only use the first line
|
289
|
+
message = message.split("\n").first.strip
|
290
|
+
@git_service.commit(message)
|
291
|
+
@spinner.success("ā Commit created successfully!".green)
|
292
|
+
|
293
|
+
# Save to history if enabled
|
294
|
+
save_to_history(message, diff)
|
295
|
+
end
|
296
|
+
|
297
|
+
def save_to_history(message, diff)
|
298
|
+
return unless @settings.get(:save_history)
|
299
|
+
|
300
|
+
metadata = {
|
301
|
+
files: @git_service.get_staged_files,
|
302
|
+
diff_size: diff.length,
|
303
|
+
style: @options[:style] || @settings.get(:commit_style)
|
304
|
+
}
|
305
|
+
|
306
|
+
@history_service.save_commit(message, metadata)
|
307
|
+
end
|
308
|
+
|
309
|
+
def cancel_operation
|
310
|
+
puts "Operation cancelled.".yellow
|
311
|
+
exit 0
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|