dopstick 0.0.1
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/.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.
|