ikuzo 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/LICENSE +21 -0
- data/README.md +120 -0
- data/bin/ikuzo +9 -0
- data/ikuzo.gemspec +27 -0
- data/lib/ikuzo/cli.rb +136 -0
- data/lib/ikuzo/messages.rb +201 -0
- data/lib/ikuzo/version.rb +5 -0
- data/lib/ikuzo.rb +11 -0
- metadata +81 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 341ee328303de83855560af0ab990e8c599d9fae811cf94de96e86057c83b26e
|
|
4
|
+
data.tar.gz: e062e1eb9fef1001223c9b144419e7e776d4f45e3e9d32d62d324aa7df08646b
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c178da9edd66460dbe86f01fc95478423f62c917ca5c62df24c3f87cd2b14fc9e1ef0222951d29bd8f3b097f5161d192880a66937fe1ac7b906953ed891cb881
|
|
7
|
+
data.tar.gz: 651e3429246c11d481bf39e57b629f968b09cc8be1f44958ff1aaca63c6f841783c4c1eda74f5535d4f7dc204719719c60977836456f6c94ada09878773f17af
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Dang Quang Minh
|
|
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 all
|
|
13
|
+
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 THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Ikuzo
|
|
2
|
+
|
|
3
|
+
Ikuzo is a Ruby gem that generates short, motivational commit messages for developers. Use it as a CLI tool or as a library inside your scripts when you need an instant morale boost.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
gem install ikuzo
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
If you are developing locally:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bundle install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### CLI
|
|
20
|
+
|
|
21
|
+
Outputs vary because messages are chosen at random. Ikuzo commits automatically; add `--no-commit` if you only want to print the message.
|
|
22
|
+
|
|
23
|
+
Commit with a random message (default: feat):
|
|
24
|
+
|
|
25
|
+
$ ikuzo
|
|
26
|
+
git commit -m "feat: main linted the vibes not the code"
|
|
27
|
+
[main abc1234] feat: main linted the vibes not the code
|
|
28
|
+
1 file changed, 1 insertion(+)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Print a random message from a specific category without committing:
|
|
32
|
+
|
|
33
|
+
$ ikuzo funny --no-commit
|
|
34
|
+
This commit was pair-programmed with caffeine.
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Commit with a random message explicitly (also default behavior):
|
|
38
|
+
|
|
39
|
+
$ ikuzo commit
|
|
40
|
+
git commit -m "It compiled on my machine, scout's honor."
|
|
41
|
+
[main abc1234] It compiled on my machine, scout's honor.
|
|
42
|
+
1 file changed, 1 insertion(+)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Skip committing and just print the message:
|
|
46
|
+
|
|
47
|
+
$ ikuzo --no-commit
|
|
48
|
+
feat: main linted the vibes not the code
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Specify a category explicitly and commit:
|
|
52
|
+
|
|
53
|
+
$ ikuzo --category dev
|
|
54
|
+
git commit -m "Logs cleaned, metrics gleam."
|
|
55
|
+
[main ghi9012] Logs cleaned, metrics gleam.
|
|
56
|
+
1 file changed, 1 insertion(+)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Generate a Conventional Commit message from the current branch (omit `--no-commit` to auto commit):
|
|
60
|
+
|
|
61
|
+
$ ikuzo feat --no-commit
|
|
62
|
+
feat: main no rubber duck was harmed in this fix
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Pick any Conventional Commit type that you need:
|
|
66
|
+
|
|
67
|
+
$ ikuzo fix
|
|
68
|
+
git commit -m "fix: main stack trace more like snack trace"
|
|
69
|
+
[main jkl3456] fix: main stack trace more like snack trace
|
|
70
|
+
1 file changed, 1 insertion(+)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Supported types align with the Conventional Commits 1.0.0 spec: build, ci, chore, docs, feat, fix, perf, refactor, revert, style, and test.
|
|
74
|
+
|
|
75
|
+
List available categories:
|
|
76
|
+
|
|
77
|
+
$ ikuzo --list-categories
|
|
78
|
+
Available categories:
|
|
79
|
+
- general
|
|
80
|
+
- funny
|
|
81
|
+
- motivation
|
|
82
|
+
- dev
|
|
83
|
+
- build - Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
|
84
|
+
- ci - Changes to CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
|
|
85
|
+
- chore - Changes which don't affect source code or tests e.g. build process, auxiliary tools, libraries
|
|
86
|
+
- docs - Documentation only changes
|
|
87
|
+
- feat
|
|
88
|
+
- fix
|
|
89
|
+
- perf
|
|
90
|
+
- refactor
|
|
91
|
+
- revert
|
|
92
|
+
- style
|
|
93
|
+
- test
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Show the installed version:
|
|
97
|
+
|
|
98
|
+
$ ikuzo --version
|
|
99
|
+
0.1.0
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Each Conventional Commit category builds a `<type>: ...` message from your current Git branch, appends a cleaned-up motivational quip, and falls back to a default subject if the branch cannot be detected.
|
|
103
|
+
|
|
104
|
+
### Library
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
require "ikuzo"
|
|
108
|
+
|
|
109
|
+
message = Ikuzo.random
|
|
110
|
+
# Defaults to the feat category
|
|
111
|
+
puts message
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Development
|
|
115
|
+
|
|
116
|
+
After checking out the repo, run `bundle install` to install dependencies. You can run `bundle exec rake release` to build and release the gem.
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
|
|
120
|
+
MIT License © 2025 Dang Quang Minh
|
data/bin/ikuzo
ADDED
data/ikuzo.gemspec
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require_relative "lib/ikuzo/version"
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |spec|
|
|
4
|
+
spec.name = "ikuzo"
|
|
5
|
+
spec.version = Ikuzo::VERSION
|
|
6
|
+
spec.authors = ["Dang Quang Minh"]
|
|
7
|
+
spec.email = ["ojisanchamchi@gmail.com"]
|
|
8
|
+
|
|
9
|
+
spec.summary = "Generate fun, motivational commit messages."
|
|
10
|
+
spec.description = "Ikuzo delivers short, humorous, and motivational commit messages for developers via both CLI and library usage."
|
|
11
|
+
spec.homepage = "https://github.com/ojisanchamchi/ruby_ikuzo#readme"
|
|
12
|
+
spec.license = "MIT"
|
|
13
|
+
|
|
14
|
+
spec.required_ruby_version = ">= 2.7"
|
|
15
|
+
|
|
16
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
17
|
+
spec.metadata["source_code_uri"] = "https://github.com/ojisanchamchi/ruby_ikuzo"
|
|
18
|
+
spec.metadata["changelog_uri"] = "https://github.com/ojisanchamchi/ruby_ikuzo/releases"
|
|
19
|
+
|
|
20
|
+
spec.files = Dir.glob("lib/**/*.rb") + %w[README.md LICENSE ikuzo.gemspec bin/ikuzo]
|
|
21
|
+
spec.bindir = "bin"
|
|
22
|
+
spec.executables = ["ikuzo"]
|
|
23
|
+
spec.require_paths = ["lib"]
|
|
24
|
+
|
|
25
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
|
26
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
|
27
|
+
end
|
data/lib/ikuzo/cli.rb
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "optparse"
|
|
4
|
+
|
|
5
|
+
module Ikuzo
|
|
6
|
+
# CLI entry point for generating random commit messages.
|
|
7
|
+
class CLI
|
|
8
|
+
def initialize(argv, stdout: $stdout, stderr: $stderr, kernel: Kernel)
|
|
9
|
+
@argv = argv.dup
|
|
10
|
+
@stdout = stdout
|
|
11
|
+
@stderr = stderr
|
|
12
|
+
@kernel = kernel
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def run
|
|
16
|
+
options = parse_options
|
|
17
|
+
|
|
18
|
+
if options[:list_categories]
|
|
19
|
+
print_categories
|
|
20
|
+
return exit_success
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
message = Messages.random(options[:category])
|
|
24
|
+
@stdout.puts(message)
|
|
25
|
+
|
|
26
|
+
return exit_success unless options[:commit]
|
|
27
|
+
|
|
28
|
+
commit_with(message)
|
|
29
|
+
rescue OptionParser::ParseError => e
|
|
30
|
+
@stderr.puts(e.message)
|
|
31
|
+
@stderr.puts(option_parser.summarize.join)
|
|
32
|
+
exit_failure
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def parse_options
|
|
38
|
+
options = {
|
|
39
|
+
commit: true,
|
|
40
|
+
list_categories: false,
|
|
41
|
+
category: nil
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
categories_text = Messages.categories.join(", ")
|
|
45
|
+
option_parser.on("-cCATEGORY", "--category=CATEGORY", "Filter by category (#{categories_text}). Default: #{Messages::DEFAULT_CATEGORY}") do |category|
|
|
46
|
+
options[:category] = category
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
option_parser.on("--commit", "Run `git commit -m` with the generated message") do
|
|
50
|
+
options[:commit] = true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
option_parser.on("--no-commit", "Only print the message; skip running git commit") do
|
|
54
|
+
options[:commit] = false
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
option_parser.on("--list-categories", "List available message categories") do
|
|
58
|
+
options[:list_categories] = true
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
option_parser.on("-v", "--version", "Print version") do
|
|
62
|
+
@stdout.puts(Ikuzo::VERSION)
|
|
63
|
+
exit_success
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
option_parser.on("-h", "--help", "Show this help message") do
|
|
67
|
+
@stdout.puts(option_parser)
|
|
68
|
+
exit_success
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
option_parser.parse!(@argv)
|
|
72
|
+
apply_positional_arguments(options)
|
|
73
|
+
options
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def option_parser
|
|
77
|
+
@option_parser ||= OptionParser.new do |opts|
|
|
78
|
+
opts.banner = "Usage: ikuzo [options] [category]"
|
|
79
|
+
opts.separator("")
|
|
80
|
+
opts.separator("Examples:")
|
|
81
|
+
opts.separator(" ikuzo")
|
|
82
|
+
opts.separator(" ikuzo funny")
|
|
83
|
+
opts.separator(" ikuzo feat --no-commit")
|
|
84
|
+
opts.separator(" ikuzo fix")
|
|
85
|
+
opts.separator(" ikuzo --category motivation --no-commit")
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def apply_positional_arguments(options)
|
|
90
|
+
@argv.each do |arg|
|
|
91
|
+
normalized = arg.to_s.strip.downcase
|
|
92
|
+
next if normalized.empty?
|
|
93
|
+
|
|
94
|
+
if category_argument?(normalized) && options[:category].nil?
|
|
95
|
+
options[:category] = normalized
|
|
96
|
+
elsif normalized == "commit"
|
|
97
|
+
options[:commit] = true
|
|
98
|
+
elsif normalized == "no-commit" || normalized == "print"
|
|
99
|
+
options[:commit] = false
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def category_argument?(value)
|
|
105
|
+
Messages.categories.include?(value.to_sym)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def commit_with(message)
|
|
109
|
+
success = @kernel.system("git", "commit", "-m", message)
|
|
110
|
+
return exit_success if success
|
|
111
|
+
|
|
112
|
+
@stderr.puts("git commit failed. Please ensure you're inside a Git repository with staged changes.")
|
|
113
|
+
exit_failure
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def print_categories
|
|
117
|
+
@stdout.puts("Available categories:")
|
|
118
|
+
Messages.categories.each do |category|
|
|
119
|
+
description = Messages.conventional_type_description(category)
|
|
120
|
+
if description
|
|
121
|
+
@stdout.puts(" - #{category} - #{description}")
|
|
122
|
+
else
|
|
123
|
+
@stdout.puts(" - #{category}")
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def exit_success
|
|
129
|
+
@kernel.exit(0)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def exit_failure
|
|
133
|
+
@kernel.exit(1)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "open3"
|
|
4
|
+
|
|
5
|
+
module Ikuzo
|
|
6
|
+
# Provides random commit messages grouped by category.
|
|
7
|
+
class Messages
|
|
8
|
+
DEFAULT_CATEGORY = :feat
|
|
9
|
+
DEFAULT_SUBJECT_CATEGORY = :funny
|
|
10
|
+
DEFAULT_CONVENTIONAL_SUBJECT = "update functionality"
|
|
11
|
+
|
|
12
|
+
CONVENTIONAL_TYPES = {
|
|
13
|
+
build: "Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)",
|
|
14
|
+
ci: "Changes to CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)",
|
|
15
|
+
chore: "Changes which don't affect source code or tests e.g. build process, auxiliary tools, libraries",
|
|
16
|
+
docs: "Documentation only changes",
|
|
17
|
+
feat: "A new feature",
|
|
18
|
+
fix: "A bug fix",
|
|
19
|
+
perf: "A change that improves performance",
|
|
20
|
+
refactor: "A change that neither fixes a bug nor adds a feature",
|
|
21
|
+
revert: "Revert something",
|
|
22
|
+
style: "Changes that do not affect the meaning of the code (formatting, missing semi-colons, etc.)",
|
|
23
|
+
test: "Adding missing tests or correcting existing tests"
|
|
24
|
+
}.freeze
|
|
25
|
+
|
|
26
|
+
STATIC_CATALOG = {
|
|
27
|
+
general: [
|
|
28
|
+
"Ship it! 🚀",
|
|
29
|
+
"Refactor today, thrive tomorrow.",
|
|
30
|
+
"Tests green, vibes high.",
|
|
31
|
+
"Merge dreams into main.",
|
|
32
|
+
"Less yak, more ship. 🪒",
|
|
33
|
+
"Deploy like nobody's watching.",
|
|
34
|
+
"Debugging wizard at work.",
|
|
35
|
+
"Automate the boring brilliance.",
|
|
36
|
+
"Feature flag? More like feature brag.",
|
|
37
|
+
"Keyboard fueled by optimism.",
|
|
38
|
+
"Pixels aligned, spirits lifted.",
|
|
39
|
+
"Compile confidence, execute courage.",
|
|
40
|
+
"Keep calm and push to main 🧘♂️",
|
|
41
|
+
"Documentation whispers success.",
|
|
42
|
+
"Breakpoints? Not today!",
|
|
43
|
+
"Commit like you mean it.",
|
|
44
|
+
"Sprint with a smile 🙂",
|
|
45
|
+
"Code, coffee, conquer.",
|
|
46
|
+
"Patching bugs with high-fives.",
|
|
47
|
+
"From TODO to ta-da!"
|
|
48
|
+
].freeze,
|
|
49
|
+
funny: [
|
|
50
|
+
"It compiled on my machine, scout's honor.",
|
|
51
|
+
"Embracing the chaos-driven-dev methodology.",
|
|
52
|
+
"This commit was pair-programmed with caffeine.",
|
|
53
|
+
"¯\\_(ツ)_/¯ ship first, debug later.",
|
|
54
|
+
"Plot twist: it actually worked.",
|
|
55
|
+
"Stack trace? More like snack trace.",
|
|
56
|
+
"Linted the vibes, not the code.",
|
|
57
|
+
"Documenting bugs as future features.",
|
|
58
|
+
"No rubber duck was harmed in this fix.",
|
|
59
|
+
"Debugger? I barely know her!"
|
|
60
|
+
].freeze,
|
|
61
|
+
motivation: [
|
|
62
|
+
"Great code starts with this commit.",
|
|
63
|
+
"Refine, refuel, release. 🔁",
|
|
64
|
+
"Iteration builds innovation.",
|
|
65
|
+
"Little wins power big releases.",
|
|
66
|
+
"Stay curious, ship bravely.",
|
|
67
|
+
"Progress is a pull request away.",
|
|
68
|
+
"Keep building, keep believing.",
|
|
69
|
+
"Quality in, confidence out.",
|
|
70
|
+
"Momentum loves momentum.",
|
|
71
|
+
"One more push toward greatness."
|
|
72
|
+
].freeze,
|
|
73
|
+
dev: [
|
|
74
|
+
"Optimized and ready for prod traffic.",
|
|
75
|
+
"Refactoring debts into assets.",
|
|
76
|
+
"Test coverage just leveled up.",
|
|
77
|
+
"Unlocking feature flags with flair.",
|
|
78
|
+
"API contracts honored, scouts promise.",
|
|
79
|
+
"Latency drops, morale pops.",
|
|
80
|
+
"Logs cleaned, metrics gleam.",
|
|
81
|
+
"DevEx boosted, friction busted.",
|
|
82
|
+
"Main branch stays evergreen.",
|
|
83
|
+
"CI lights are greener than ever."
|
|
84
|
+
].freeze
|
|
85
|
+
}.freeze
|
|
86
|
+
|
|
87
|
+
CONVENTIONAL_CATALOG = CONVENTIONAL_TYPES.each_with_object({}) do |(type, _), hash|
|
|
88
|
+
hash[type] = -> { conventional_message(type) }
|
|
89
|
+
end.freeze
|
|
90
|
+
|
|
91
|
+
CATALOG = STATIC_CATALOG.merge(CONVENTIONAL_CATALOG).freeze
|
|
92
|
+
|
|
93
|
+
def self.random(category = nil)
|
|
94
|
+
category = normalize_category(category)
|
|
95
|
+
candidates = messages_for(category)
|
|
96
|
+
return candidates.sample unless candidates.empty?
|
|
97
|
+
|
|
98
|
+
messages_for(DEFAULT_CATEGORY).sample
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def self.categories
|
|
102
|
+
CATALOG.keys
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def self.conventional_types
|
|
106
|
+
CONVENTIONAL_TYPES.keys
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def self.conventional_type_description(type)
|
|
110
|
+
CONVENTIONAL_TYPES[type.to_sym] if type
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def self.conventional_type?(value)
|
|
114
|
+
return false unless value
|
|
115
|
+
|
|
116
|
+
CONVENTIONAL_TYPES.key?(value.to_sym)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def self.messages_for(category)
|
|
120
|
+
category = normalize_category(category)
|
|
121
|
+
entry = CATALOG.fetch(category) { CATALOG.fetch(DEFAULT_CATEGORY) }
|
|
122
|
+
resolve_entry(entry)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def self.normalize_category(category)
|
|
126
|
+
return DEFAULT_CATEGORY unless category
|
|
127
|
+
|
|
128
|
+
sym = category.to_s.strip.downcase.to_sym
|
|
129
|
+
categories.include?(sym) ? sym : DEFAULT_CATEGORY
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def self.resolve_entry(entry)
|
|
133
|
+
case entry
|
|
134
|
+
when Proc
|
|
135
|
+
value = entry.call
|
|
136
|
+
return resolve_entry(CATALOG.fetch(DEFAULT_CATEGORY)) if value.nil? || (value.respond_to?(:empty?) && value.empty?)
|
|
137
|
+
|
|
138
|
+
Array(value)
|
|
139
|
+
when Array
|
|
140
|
+
entry
|
|
141
|
+
else
|
|
142
|
+
Array(entry)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
private_class_method :resolve_entry
|
|
146
|
+
|
|
147
|
+
def self.conventional_message(type)
|
|
148
|
+
subject_parts = [branch_subject, sanitized_default_subject].compact.reject(&:empty?)
|
|
149
|
+
subject = subject_parts.join(" ").strip
|
|
150
|
+
subject = DEFAULT_CONVENTIONAL_SUBJECT if subject.empty?
|
|
151
|
+
"#{type}: #{subject}"
|
|
152
|
+
end
|
|
153
|
+
private_class_method :conventional_message
|
|
154
|
+
|
|
155
|
+
def self.current_branch
|
|
156
|
+
stdout, status = Open3.capture2("git", "rev-parse", "--abbrev-ref", "HEAD")
|
|
157
|
+
return unless status.success?
|
|
158
|
+
|
|
159
|
+
branch = stdout.strip
|
|
160
|
+
return if branch.empty? || branch == "HEAD"
|
|
161
|
+
|
|
162
|
+
branch
|
|
163
|
+
rescue StandardError
|
|
164
|
+
nil
|
|
165
|
+
end
|
|
166
|
+
private_class_method :current_branch
|
|
167
|
+
|
|
168
|
+
def self.branch_subject
|
|
169
|
+
branch = current_branch
|
|
170
|
+
return unless branch
|
|
171
|
+
|
|
172
|
+
short_name = branch.split("/").last
|
|
173
|
+
sanitize_subject(short_name)
|
|
174
|
+
end
|
|
175
|
+
private_class_method :branch_subject
|
|
176
|
+
|
|
177
|
+
def self.sanitized_default_subject
|
|
178
|
+
source_category = STATIC_CATALOG.key?(DEFAULT_CATEGORY) ? DEFAULT_CATEGORY : DEFAULT_SUBJECT_CATEGORY
|
|
179
|
+
entry = STATIC_CATALOG[source_category] || STATIC_CATALOG[DEFAULT_SUBJECT_CATEGORY]
|
|
180
|
+
return unless entry
|
|
181
|
+
|
|
182
|
+
candidates = resolve_entry(entry)
|
|
183
|
+
message = candidates.sample
|
|
184
|
+
sanitized = sanitize_subject(message)
|
|
185
|
+
sanitized unless sanitized.empty?
|
|
186
|
+
end
|
|
187
|
+
private_class_method :sanitized_default_subject
|
|
188
|
+
|
|
189
|
+
def self.sanitize_subject(value)
|
|
190
|
+
return "" unless value
|
|
191
|
+
|
|
192
|
+
value
|
|
193
|
+
.to_s
|
|
194
|
+
.downcase
|
|
195
|
+
.gsub(/[^a-z0-9\s\-]/, " ")
|
|
196
|
+
.gsub(/\s+/, " ")
|
|
197
|
+
.strip
|
|
198
|
+
end
|
|
199
|
+
private_class_method :sanitize_subject
|
|
200
|
+
end
|
|
201
|
+
end
|
data/lib/ikuzo.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ikuzo
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Dang Quang Minh
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: bundler
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rake
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '13.0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '13.0'
|
|
40
|
+
description: Ikuzo delivers short, humorous, and motivational commit messages for
|
|
41
|
+
developers via both CLI and library usage.
|
|
42
|
+
email:
|
|
43
|
+
- ojisanchamchi@gmail.com
|
|
44
|
+
executables:
|
|
45
|
+
- ikuzo
|
|
46
|
+
extensions: []
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
files:
|
|
49
|
+
- LICENSE
|
|
50
|
+
- README.md
|
|
51
|
+
- bin/ikuzo
|
|
52
|
+
- ikuzo.gemspec
|
|
53
|
+
- lib/ikuzo.rb
|
|
54
|
+
- lib/ikuzo/cli.rb
|
|
55
|
+
- lib/ikuzo/messages.rb
|
|
56
|
+
- lib/ikuzo/version.rb
|
|
57
|
+
homepage: https://github.com/ojisanchamchi/ruby_ikuzo#readme
|
|
58
|
+
licenses:
|
|
59
|
+
- MIT
|
|
60
|
+
metadata:
|
|
61
|
+
homepage_uri: https://github.com/ojisanchamchi/ruby_ikuzo#readme
|
|
62
|
+
source_code_uri: https://github.com/ojisanchamchi/ruby_ikuzo
|
|
63
|
+
changelog_uri: https://github.com/ojisanchamchi/ruby_ikuzo/releases
|
|
64
|
+
rdoc_options: []
|
|
65
|
+
require_paths:
|
|
66
|
+
- lib
|
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: '2.7'
|
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '0'
|
|
77
|
+
requirements: []
|
|
78
|
+
rubygems_version: 3.6.9
|
|
79
|
+
specification_version: 4
|
|
80
|
+
summary: Generate fun, motivational commit messages.
|
|
81
|
+
test_files: []
|