dopstick 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/FUNDING.yml +4 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +41 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +38 -0
- data/.github/workflows/tests.yml +55 -0
- data/.gitignore +11 -0
- data/.rubocop.yml +21 -0
- data/CHANGELOG.md +16 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONTRIBUTING.md +79 -0
- data/Gemfile +5 -0
- data/LICENSE.md +20 -0
- data/README.md +56 -0
- data/Rakefile +15 -0
- data/bin/console +16 -0
- data/bin/setup +10 -0
- data/dopstick.gemspec +45 -0
- data/exe/dopstick +5 -0
- data/lib/dopstick.rb +12 -0
- data/lib/dopstick/cli.rb +89 -0
- data/lib/dopstick/generator.rb +214 -0
- data/lib/dopstick/refinements.rb +24 -0
- data/lib/dopstick/templates/CHANGELOG.md +16 -0
- data/lib/dopstick/templates/active_record.erb +23 -0
- data/lib/dopstick/templates/bin.erb +5 -0
- data/lib/dopstick/templates/bug_report.erb +41 -0
- data/lib/dopstick/templates/cli.erb +3 -0
- data/lib/dopstick/templates/cli_class.erb +19 -0
- data/lib/dopstick/templates/coc.erb +74 -0
- data/lib/dopstick/templates/console.erb +16 -0
- data/lib/dopstick/templates/contributing.erb +80 -0
- data/lib/dopstick/templates/entry_file.erb +3 -0
- data/lib/dopstick/templates/feature_request.erb +23 -0
- data/lib/dopstick/templates/funding.erb +4 -0
- data/lib/dopstick/templates/gem_entry_file.erb +3 -0
- data/lib/dopstick/templates/gemfile.erb +5 -0
- data/lib/dopstick/templates/gemspec.erb +53 -0
- data/lib/dopstick/templates/generator.erb +3 -0
- data/lib/dopstick/templates/generator_class.erb +13 -0
- data/lib/dopstick/templates/gitignore.erb +11 -0
- data/lib/dopstick/templates/issue.erb +26 -0
- data/lib/dopstick/templates/license.erb +20 -0
- data/lib/dopstick/templates/pull_request.erb +38 -0
- data/lib/dopstick/templates/rakefile.erb +15 -0
- data/lib/dopstick/templates/readme.erb +50 -0
- data/lib/dopstick/templates/rubocop.erb +12 -0
- data/lib/dopstick/templates/setup.erb +10 -0
- data/lib/dopstick/templates/test_file.erb +9 -0
- data/lib/dopstick/templates/test_helper.erb +14 -0
- data/lib/dopstick/templates/tests_workflow.erb +73 -0
- data/lib/dopstick/templates/version.erb +3 -0
- data/lib/dopstick/version.rb +5 -0
- metadata +214 -0
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rake/testtask"
|
5
|
+
require "rubocop/rake_task"
|
6
|
+
|
7
|
+
Rake::TestTask.new(:test) do |t|
|
8
|
+
t.libs << "test"
|
9
|
+
t.libs << "lib"
|
10
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
11
|
+
end
|
12
|
+
|
13
|
+
RuboCop::RakeTask.new
|
14
|
+
|
15
|
+
task default: %i[test rubocop]
|
data/bin/console
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "dopstick"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
begin
|
11
|
+
require "pry"
|
12
|
+
Pry.start
|
13
|
+
rescue LoadError
|
14
|
+
require "irb"
|
15
|
+
IRB.start(__FILE__)
|
16
|
+
end
|
data/bin/setup
ADDED
data/dopstick.gemspec
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./lib/dopstick/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "dopstick"
|
7
|
+
spec.version = Dopstick::VERSION
|
8
|
+
spec.authors = ["Nando Vieira"]
|
9
|
+
spec.email = ["me@fnando.com"]
|
10
|
+
|
11
|
+
spec.summary = "Generate a project skeleton for creating a rubygem"
|
12
|
+
spec.description = spec.summary
|
13
|
+
spec.license = "MIT"
|
14
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
|
15
|
+
|
16
|
+
github_url = "https://github.com/fnando/dopstick"
|
17
|
+
github_tree_url = "#{github_url}/blob/v#{spec.version}"
|
18
|
+
|
19
|
+
spec.homepage = github_url
|
20
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
21
|
+
spec.metadata["bug_tracker_uri"] = "#{github_url}/issues"
|
22
|
+
spec.metadata["source_code_uri"] = github_tree_url
|
23
|
+
spec.metadata["changelog_uri"] = "#{github_tree_url}/CHANGELOG.md"
|
24
|
+
spec.metadata["documentation_uri"] = "#{github_tree_url}/README.md"
|
25
|
+
spec.metadata["license_uri"] = "#{github_tree_url}/LICENSE.md"
|
26
|
+
|
27
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
28
|
+
`git ls-files -z`
|
29
|
+
.split("\x0")
|
30
|
+
.reject {|f| f.match(%r{^(test|spec|features)/}) }
|
31
|
+
end
|
32
|
+
|
33
|
+
spec.bindir = "exe"
|
34
|
+
spec.executables = spec.files.grep(%r{^exe/}) {|f| File.basename(f) }
|
35
|
+
spec.require_paths = ["lib"]
|
36
|
+
|
37
|
+
spec.add_dependency "thor"
|
38
|
+
spec.add_development_dependency "minitest"
|
39
|
+
spec.add_development_dependency "minitest-utils"
|
40
|
+
spec.add_development_dependency "pry-meta"
|
41
|
+
spec.add_development_dependency "rake"
|
42
|
+
spec.add_development_dependency "rubocop"
|
43
|
+
spec.add_development_dependency "rubocop-fnando"
|
44
|
+
spec.add_development_dependency "simplecov"
|
45
|
+
end
|
data/exe/dopstick
ADDED
data/lib/dopstick.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
require "pathname"
|
5
|
+
require "thor"
|
6
|
+
|
7
|
+
module Dopstick
|
8
|
+
require_relative "dopstick/refinements"
|
9
|
+
require_relative "dopstick/version"
|
10
|
+
require_relative "dopstick/generator"
|
11
|
+
require_relative "dopstick/cli"
|
12
|
+
end
|
data/lib/dopstick/cli.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dopstick
|
4
|
+
class CLI < Thor
|
5
|
+
using Dopstick::Refinements
|
6
|
+
check_unknown_options!
|
7
|
+
|
8
|
+
def self.exit_on_failure?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "new PATH", "Create a new gem"
|
13
|
+
option :name,
|
14
|
+
default: "",
|
15
|
+
desc: "Set the gem name. Defaults to path's basename."
|
16
|
+
option :active_record,
|
17
|
+
default: false,
|
18
|
+
type: :boolean,
|
19
|
+
desc: "Set up ActiveRecord for testing."
|
20
|
+
option :author_name,
|
21
|
+
default: "",
|
22
|
+
desc: "Set author name. Defaults to `git config user.name`."
|
23
|
+
option :author_email,
|
24
|
+
default: "",
|
25
|
+
desc: "Set author email. Defaults to `git config user.email`."
|
26
|
+
option :author_github,
|
27
|
+
default: "",
|
28
|
+
desc: "Set Github username. Defaults to `git config user.github`."
|
29
|
+
option :author_paypal,
|
30
|
+
default: "",
|
31
|
+
desc: "Set Paypal account for donations. Defaults to " \
|
32
|
+
"`git config user.paypal`."
|
33
|
+
option :repository,
|
34
|
+
default: "",
|
35
|
+
desc: "Set Github repository name. Defaults to gem name."
|
36
|
+
option :description,
|
37
|
+
default: "",
|
38
|
+
desc: "Set gem description."
|
39
|
+
option :version,
|
40
|
+
default: "0.0.0",
|
41
|
+
desc: "Set package initial version."
|
42
|
+
option :bin,
|
43
|
+
default: "",
|
44
|
+
desc: "Set binary name. Also sets up Thor CLI and generator."
|
45
|
+
option :namespace,
|
46
|
+
default: "",
|
47
|
+
desc: "Set the codebase namespace. By default, it's inferred from " \
|
48
|
+
"the gem name."
|
49
|
+
option :ruby_versions,
|
50
|
+
default: %w[2.6 2.7],
|
51
|
+
type: :array,
|
52
|
+
desc: "Set Ruby versions that are officially supported. Multiple " \
|
53
|
+
"versions must separated by space."
|
54
|
+
def new(path)
|
55
|
+
options = dup_options
|
56
|
+
gem_name, namespace = expand_gem_name_and_namespace(path)
|
57
|
+
|
58
|
+
generator = Generator.new
|
59
|
+
generator.destination_root = File.expand_path(path)
|
60
|
+
generator.options = options.merge(
|
61
|
+
gem_name: gem_name,
|
62
|
+
namespace: namespace,
|
63
|
+
entry_path: namespace.underscore("/")
|
64
|
+
)
|
65
|
+
|
66
|
+
generator.invoke_all
|
67
|
+
end
|
68
|
+
|
69
|
+
no_commands do
|
70
|
+
private def dup_options
|
71
|
+
options.each_with_object({}) do |(key, value), buffer|
|
72
|
+
buffer[key.to_sym] = value
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private def expand_gem_name_and_namespace(path) # rubocop:disable Metrics/AbcSize
|
77
|
+
if options[:name].presence && options[:namespace].presence
|
78
|
+
[options[:name], options[:namespace]]
|
79
|
+
elsif options[:name].presence
|
80
|
+
[options[:name], options[:name].camelize]
|
81
|
+
elsif options[:namespace].presence
|
82
|
+
[options[:namespace].underscore("-"), options[:namespace]]
|
83
|
+
else
|
84
|
+
[File.basename(path), File.basename(path).camelize]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dopstick
|
4
|
+
class Generator < Thor::Group # rubocop:disable Metrics/ClassLength
|
5
|
+
using Dopstick::Refinements
|
6
|
+
|
7
|
+
include Thor::Actions
|
8
|
+
|
9
|
+
def self.exit_on_failure?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :options
|
14
|
+
|
15
|
+
desc "Generate a new gem folder structure"
|
16
|
+
|
17
|
+
def self.source_root
|
18
|
+
File.join(__dir__, "templates")
|
19
|
+
end
|
20
|
+
|
21
|
+
def copy_gemspec
|
22
|
+
template "gemspec.erb", "#{gem_name}.gemspec"
|
23
|
+
end
|
24
|
+
|
25
|
+
def copy_license
|
26
|
+
template "license.erb", "LICENSE.md"
|
27
|
+
end
|
28
|
+
|
29
|
+
def copy_coc
|
30
|
+
template "coc.erb", "CODE_OF_CONDUCT.md"
|
31
|
+
end
|
32
|
+
|
33
|
+
def copy_readme
|
34
|
+
template "readme.erb", "README.md"
|
35
|
+
end
|
36
|
+
|
37
|
+
def copy_changelog
|
38
|
+
copy_file "CHANGELOG.md"
|
39
|
+
end
|
40
|
+
|
41
|
+
def copy_contributing
|
42
|
+
template "contributing.erb", "CONTRIBUTING.md"
|
43
|
+
end
|
44
|
+
|
45
|
+
def copy_github_templates
|
46
|
+
template "funding.erb", ".github/FUNDING.yml"
|
47
|
+
template "tests_workflow.erb", ".github/workflows/tests.yml"
|
48
|
+
template "bug_report.erb", ".github/ISSUE_TEMPLATE/bug_report.md"
|
49
|
+
template "feature_request.erb",
|
50
|
+
".github/ISSUE_TEMPLATE/feature_request.md"
|
51
|
+
template "pull_request.erb", ".github/PULL_REQUEST_TEMPLATE.md"
|
52
|
+
end
|
53
|
+
|
54
|
+
def copy_rakefile
|
55
|
+
template "rakefile.erb", "Rakefile"
|
56
|
+
end
|
57
|
+
|
58
|
+
def copy_rubocop
|
59
|
+
template "rubocop.erb", ".rubocop.yml"
|
60
|
+
end
|
61
|
+
|
62
|
+
def copy_gitignore
|
63
|
+
template "gitignore.erb", ".gitignore"
|
64
|
+
end
|
65
|
+
|
66
|
+
def copy_gemfile
|
67
|
+
template "gemfile.erb", "Gemfile"
|
68
|
+
end
|
69
|
+
|
70
|
+
def copy_bins
|
71
|
+
template "console.erb", "bin/console"
|
72
|
+
template "setup.erb", "bin/setup"
|
73
|
+
in_root { run "chmod +x bin/*" }
|
74
|
+
end
|
75
|
+
|
76
|
+
def create_entry_file
|
77
|
+
if entry_path.include?("/")
|
78
|
+
template "gem_entry_file.erb", "lib/#{gem_name}.rb"
|
79
|
+
end
|
80
|
+
|
81
|
+
template "entry_file.erb", "lib/#{entry_path}.rb"
|
82
|
+
end
|
83
|
+
|
84
|
+
def create_version_file
|
85
|
+
template "version.erb", "lib/#{entry_path}/version.rb"
|
86
|
+
end
|
87
|
+
|
88
|
+
def copy_test_files
|
89
|
+
template "test_helper.erb", "test/test_helper.rb"
|
90
|
+
template "test_file.erb", "test/#{entry_path}_test.rb"
|
91
|
+
end
|
92
|
+
|
93
|
+
def copy_binary_files
|
94
|
+
return unless options[:bin].presence
|
95
|
+
|
96
|
+
template "cli.erb", "lib/#{entry_path}/cli.rb"
|
97
|
+
template "generator.erb", "lib/#{entry_path}/generator.rb"
|
98
|
+
template "bin.erb", "exe/#{options[:bin]}"
|
99
|
+
create_file "lib/#{entry_path}/templates/.keep"
|
100
|
+
in_root { run "chmod +x exe/*" }
|
101
|
+
end
|
102
|
+
|
103
|
+
def copy_active_record_files
|
104
|
+
return unless options[:active_record]
|
105
|
+
|
106
|
+
template "active_record.erb", "test/support/active_record.rb"
|
107
|
+
end
|
108
|
+
|
109
|
+
def initialize_repo
|
110
|
+
in_root do
|
111
|
+
run "git init --initial-branch=main", capture: true
|
112
|
+
run "git add .", capture: true
|
113
|
+
run "git add bin --force", capture: true
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
no_commands do # rubocop:disable Metrics/BlockLength
|
118
|
+
def gem_name
|
119
|
+
options[:gem_name]
|
120
|
+
end
|
121
|
+
|
122
|
+
def entry_path
|
123
|
+
options[:entry_path]
|
124
|
+
end
|
125
|
+
|
126
|
+
def user_name
|
127
|
+
@user_name ||= options[:author_name].presence ||
|
128
|
+
`git config --global user.name`.chomp
|
129
|
+
end
|
130
|
+
|
131
|
+
def user_email
|
132
|
+
@user_email ||= options[:author_email].presence ||
|
133
|
+
`git config --global user.email`.chomp
|
134
|
+
end
|
135
|
+
|
136
|
+
def github_user
|
137
|
+
@github_user ||= options[:author_github].presence || begin
|
138
|
+
user = `git config --global user.github`.chomp
|
139
|
+
user.empty? ? "[USER]" : user
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def paypal_user
|
144
|
+
@paypal_user ||= options[:author_paypal].presence || begin
|
145
|
+
user = `git config --global user.paypal`.chomp
|
146
|
+
user.empty? ? "[USER]" : user
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def github_url
|
151
|
+
"https://github.com/#{github_user}/#{gem_name}"
|
152
|
+
end
|
153
|
+
|
154
|
+
def ruby_versions
|
155
|
+
options[:ruby_versions]
|
156
|
+
end
|
157
|
+
|
158
|
+
def const_names
|
159
|
+
@const_names ||= options[:namespace].split("::")
|
160
|
+
end
|
161
|
+
|
162
|
+
def const_names_size
|
163
|
+
@const_names_size ||= const_names.size
|
164
|
+
end
|
165
|
+
|
166
|
+
def render_tree(skip_content_spaces = false, &block) # rubocop:disable Style/OptionalBooleanParameter
|
167
|
+
content = []
|
168
|
+
|
169
|
+
const_names.each_with_index do |name, count|
|
170
|
+
content << (" " * count) + "module #{name}"
|
171
|
+
end
|
172
|
+
|
173
|
+
spacer = skip_content_spaces ? "" : " "
|
174
|
+
|
175
|
+
content << (spacer * const_names_size) + block.call
|
176
|
+
|
177
|
+
(const_names_size - 1).downto(0) do |count|
|
178
|
+
content << "#{' ' * count}end"
|
179
|
+
end
|
180
|
+
|
181
|
+
content.join("\n")
|
182
|
+
end
|
183
|
+
|
184
|
+
def erb(file)
|
185
|
+
ERB.new(File.read("#{__dir__}/templates/#{file}")).result binding
|
186
|
+
end
|
187
|
+
|
188
|
+
def render_cli
|
189
|
+
cli_class = erb("cli_class.erb")
|
190
|
+
.chomp
|
191
|
+
.gsub(/^(.)/m, "#{' ' * const_names_size}\\1")
|
192
|
+
|
193
|
+
render_tree(true) { cli_class }
|
194
|
+
end
|
195
|
+
|
196
|
+
def render_generator
|
197
|
+
generator_class = erb("generator_class.erb")
|
198
|
+
.chomp
|
199
|
+
.gsub(/^(.)/m, "#{' ' * const_names_size}\\1")
|
200
|
+
|
201
|
+
render_tree(true) { generator_class }
|
202
|
+
end
|
203
|
+
|
204
|
+
def oldest_ruby_version
|
205
|
+
version = options[:ruby_versions]
|
206
|
+
.map {|v| Gem::Version.new(v) }
|
207
|
+
.min
|
208
|
+
.canonical_segments
|
209
|
+
|
210
|
+
[*version, 0].take(3).join(".")
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dopstick
|
4
|
+
module Refinements
|
5
|
+
refine String do
|
6
|
+
def presence
|
7
|
+
empty? ? nil : self
|
8
|
+
end
|
9
|
+
|
10
|
+
def camelize
|
11
|
+
split("-")
|
12
|
+
.map {|word| word.split("_").map(&:capitalize).join }
|
13
|
+
.join("::")
|
14
|
+
end
|
15
|
+
|
16
|
+
def underscore(separator = "/")
|
17
|
+
split("::")
|
18
|
+
.map {|word| word.gsub(/([A-Z]+)/m, "_\\1")[1..-1] }
|
19
|
+
.join(separator)
|
20
|
+
.downcase
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
<!--
|
4
|
+
Prefix your message with one of the following:
|
5
|
+
|
6
|
+
- [Added] for new features.
|
7
|
+
- [Changed] for changes in existing functionality.
|
8
|
+
- [Deprecated] for soon-to-be removed features.
|
9
|
+
- [Removed] for now removed features.
|
10
|
+
- [Fixed] for any bug fixes.
|
11
|
+
- [Security] in case of vulnerabilities.
|
12
|
+
-->
|
13
|
+
|
14
|
+
## Unreleased
|
15
|
+
|
16
|
+
- Initial release.
|