rubysmith 0.10.0 → 0.14.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.adoc +111 -41
  4. data/lib/rubysmith/builder.rb +11 -16
  5. data/lib/rubysmith/builders/bundler.rb +3 -3
  6. data/lib/rubysmith/builders/{ruby_critic.rb → circle_ci.rb} +6 -5
  7. data/lib/rubysmith/builders/console.rb +1 -1
  8. data/lib/rubysmith/builders/core.rb +6 -2
  9. data/lib/rubysmith/builders/documentation/change.rb +32 -0
  10. data/lib/rubysmith/builders/documentation/conduct.rb +32 -0
  11. data/lib/rubysmith/builders/documentation/contribution.rb +32 -0
  12. data/lib/rubysmith/builders/documentation/license.rb +36 -0
  13. data/lib/rubysmith/builders/documentation/readme.rb +44 -0
  14. data/lib/rubysmith/builders/git/commit.rb +1 -1
  15. data/lib/rubysmith/builders/git/setup.rb +1 -1
  16. data/lib/rubysmith/builders/git_hub.rb +34 -0
  17. data/lib/rubysmith/builders/guard.rb +1 -1
  18. data/lib/rubysmith/builders/pragma.rb +1 -1
  19. data/lib/rubysmith/builders/rake.rb +3 -1
  20. data/lib/rubysmith/builders/reek.rb +1 -1
  21. data/lib/rubysmith/builders/rspec/context.rb +1 -1
  22. data/lib/rubysmith/builders/rspec/helper.rb +1 -1
  23. data/lib/rubysmith/builders/rubocop/formatter.rb +1 -1
  24. data/lib/rubysmith/builders/rubocop/setup.rb +1 -1
  25. data/lib/rubysmith/builders/setup.rb +1 -1
  26. data/lib/rubysmith/cli/actions/build.rb +48 -0
  27. data/lib/rubysmith/cli/actions/config.rb +33 -0
  28. data/lib/rubysmith/cli/configuration/content.rb +47 -19
  29. data/lib/rubysmith/cli/configuration/defaults.yml +16 -9
  30. data/lib/rubysmith/cli/configuration/enhancers/current_time.rb +26 -0
  31. data/lib/rubysmith/cli/configuration/enhancers/git_hub_user.rb +33 -0
  32. data/lib/rubysmith/cli/configuration/enhancers/version.rb +26 -0
  33. data/lib/rubysmith/cli/configuration/loader.rb +15 -4
  34. data/lib/rubysmith/cli/parsers/assembler.rb +7 -9
  35. data/lib/rubysmith/cli/parsers/build.rb +174 -49
  36. data/lib/rubysmith/cli/parsers/core.rb +14 -9
  37. data/lib/rubysmith/cli/shell.rb +16 -28
  38. data/lib/rubysmith/container.rb +37 -0
  39. data/lib/rubysmith/identity.rb +2 -2
  40. data/lib/rubysmith/renderers/erb.rb +1 -1
  41. data/lib/rubysmith/renderers/namespace.rb +2 -2
  42. data/lib/rubysmith/templates/%project_name%/.circleci/config.yml.erb +31 -0
  43. data/lib/rubysmith/templates/%project_name%/.github/ISSUE_TEMPLATE.md.erb +14 -0
  44. data/lib/rubysmith/templates/%project_name%/.github/PULL_REQUEST_TEMPLATE.md.erb +11 -0
  45. data/lib/rubysmith/templates/%project_name%/Gemfile.erb +51 -52
  46. data/lib/rubysmith/templates/%project_name%/README.adoc.erb +4 -0
  47. data/lib/rubysmith/templates/%project_name%/README.md.erb +3 -0
  48. data/lib/rubysmith/templates/%project_name%/Rakefile.erb +1 -13
  49. data/lib/rubysmith/templates/%project_name%/bin/console.erb +1 -1
  50. data/lib/rubysmith/templates/%project_name%/lib/%project_path%.rb.erb +12 -0
  51. data/lib/rubysmith/templates/%project_name%/spec/spec_helper.rb.erb +1 -1
  52. data/lib/rubysmith.rb +13 -31
  53. data.tar.gz.sig +0 -0
  54. metadata +92 -11
  55. metadata.gz.sig +0 -0
  56. data/lib/rubysmith/builders/documentation.rb +0 -57
  57. data/lib/rubysmith/cli/processors/build.rb +0 -59
  58. data/lib/rubysmith/cli/processors/config.rb +0 -31
  59. data/lib/rubysmith/templates/%project_name%/.rubycritic.yml.erb +0 -3
  60. data/lib/rubysmith/templates/%project_name%/lib/%project_name%.rb.erb +0 -3
@@ -4,13 +4,12 @@ module Rubysmith
4
4
  module CLI
5
5
  module Parsers
6
6
  # Handles parsing of Command Line Interface (CLI) build options.
7
- # :reek:TooManyMethods
8
7
  class Build
9
- def self.call(options: {}, client: CLIENT) = new(options: options, client: client).call
8
+ def self.call(...) = new(...).call
10
9
 
11
- def initialize options: {}, client: CLIENT
12
- @options = options
10
+ def initialize client: CLIENT, container: Container
13
11
  @client = client
12
+ @container = container
14
13
  end
15
14
 
16
15
  def call arguments = []
@@ -21,109 +20,235 @@ module Rubysmith
21
20
 
22
21
  private
23
22
 
24
- attr_reader :options, :client
23
+ attr_reader :client, :container
25
24
 
26
- def add_minimum
27
- client.on "--min", "Use minimum/no options." do |value|
28
- options[:build_minimum] = value
25
+ def add_amazing_print
26
+ client.on(
27
+ "--[no-]amazing_print",
28
+ "Add Amazing Print gem. #{default __method__}."
29
+ ) do |value|
30
+ configuration.build_amazing_print = value
29
31
  end
30
32
  end
31
33
 
32
- def add_amazing_print
33
- client.on "--[no-]amazing_print", "Add Amazing Print." do |value|
34
- options[:build_amazing_print] = value
34
+ def add_bundler_leak
35
+ client.on(
36
+ "--[no-]bundler-leak",
37
+ "Add Bundler Leak gem. #{default __method__}."
38
+ ) do |value|
39
+ configuration.build_bundler_leak = value
35
40
  end
36
41
  end
37
42
 
38
- def add_bundler_audit
39
- client.on "--[no-]bundler-audit", "Add Bundler Audit." do |value|
40
- options[:build_bundler_audit] = value
43
+ def add_changes
44
+ client.on(
45
+ "--[no-]changes",
46
+ "Add CHANGES documentation. #{default __method__}."
47
+ ) do |value|
48
+ configuration.build_changes = value
41
49
  end
42
50
  end
43
51
 
44
- def add_bundler_leak
45
- client.on "--[no-]bundler-leak", "Add Bundler Leak." do |value|
46
- options[:build_bundler_leak] = value
52
+ def add_console
53
+ client.on(
54
+ "--[no-]console",
55
+ "Add console script. #{default __method__}."
56
+ ) do |value|
57
+ configuration.build_console = value
47
58
  end
48
59
  end
49
60
 
50
- def add_console
51
- client.on "--[no-]console", "Add console script." do |value|
52
- options[:build_console] = value
61
+ def add_contributions
62
+ client.on(
63
+ "--[no-]contributions",
64
+ "Add CONTRIBUTING documentation. #{default __method__}."
65
+ ) do |value|
66
+ configuration.build_contributions = value
67
+ end
68
+ end
69
+
70
+ def add_circle_ci
71
+ client.on(
72
+ "--[no-]circle_ci",
73
+ "Add Circle CI configuration and badge. #{default __method__}."
74
+ ) do |value|
75
+ configuration.build_circle_ci = value
53
76
  end
54
77
  end
55
78
 
56
- def add_documentation
57
- client.on "--[no-]documentation", "Add documentation." do |value|
58
- options[:build_documentation] = value
79
+ def add_conduct
80
+ client.on(
81
+ "--[no-]conduct",
82
+ "Add CODE_OF_CONDUCT documentation. #{default __method__}."
83
+ ) do |value|
84
+ configuration.build_conduct = value
85
+ end
86
+ end
87
+
88
+ def add_debug
89
+ client.on(
90
+ "--[no-]debug",
91
+ "Add Debug gem. #{default __method__}."
92
+ ) do |value|
93
+ configuration.build_debug = value
59
94
  end
60
95
  end
61
96
 
62
97
  def add_git
63
- client.on "--[no-]git", "Add Git." do |value|
64
- options[:build_git] = value
98
+ client.on(
99
+ "--[no-]git",
100
+ "Add Git. #{default __method__}."
101
+ ) do |value|
102
+ configuration.build_git = value
103
+ end
104
+ end
105
+
106
+ def add_git_hub
107
+ client.on(
108
+ "--[no-]git_hub",
109
+ "Add GitHub templates. #{default __method__}."
110
+ ) do |value|
111
+ configuration.build_git_hub = value
65
112
  end
66
113
  end
67
114
 
68
115
  def add_git_lint
69
- client.on "--[no-]git-lint", "Add Git Lint." do |value|
70
- options[:build_git_lint] = value
116
+ client.on(
117
+ "--[no-]git-lint",
118
+ "Add Git Lint gem. #{default __method__}."
119
+ ) do |value|
120
+ configuration.build_git_lint = value
71
121
  end
72
122
  end
73
123
 
74
124
  def add_guard
75
- client.on "--[no-]guard", "Add Guard." do |value|
76
- options[:build_guard] = value
125
+ client.on(
126
+ "--[no-]guard",
127
+ "Add Guard gem. #{default __method__}."
128
+ ) do |value|
129
+ configuration.build_guard = value
130
+ end
131
+ end
132
+
133
+ def add_license
134
+ client.on(
135
+ "--[no-]license",
136
+ "Add LICENSE documentation. #{default __method__}."
137
+ ) do |value|
138
+ configuration.build_license = value
77
139
  end
78
140
  end
79
141
 
80
- def add_pry
81
- client.on "--[no-]pry", "Add Pry." do |value|
82
- options[:build_pry] = value
142
+ def add_maximum
143
+ client.on(
144
+ "--max",
145
+ "Use maximum/enabled options. #{default __method__}."
146
+ ) do |value|
147
+ configuration.maximize.build_maximum = value
148
+ end
149
+ end
150
+
151
+ def add_minimum
152
+ client.on(
153
+ "--min",
154
+ "Use minimum/disabled options. #{default __method__}."
155
+ ) do |value|
156
+ configuration.minimize.build_minimum = value
157
+ end
158
+ end
159
+
160
+ def add_rake
161
+ client.on(
162
+ "--[no-]rake",
163
+ "Add Rake gem. #{default __method__}."
164
+ ) do |value|
165
+ configuration.build_rake = value
166
+ end
167
+ end
168
+
169
+ def add_readme
170
+ client.on(
171
+ "--[no-]readme",
172
+ "Add README documentation. #{default __method__}."
173
+ ) do |value|
174
+ configuration.build_readme = value
83
175
  end
84
176
  end
85
177
 
86
178
  def add_reek
87
- client.on "--[no-]reek", "Add Reek." do |value|
88
- options[:build_reek] = value
179
+ client.on(
180
+ "--[no-]reek",
181
+ "Add Reek gem. #{default __method__}."
182
+ ) do |value|
183
+ configuration.build_reek = value
89
184
  end
90
185
  end
91
186
 
92
187
  def add_refinements
93
- client.on "--[no-]refinements", "Add Refinements." do |value|
94
- options[:build_refinements] = value
188
+ client.on(
189
+ "--[no-]refinements",
190
+ "Add Refinements gem. #{default __method__}."
191
+ ) do |value|
192
+ configuration.build_refinements = value
95
193
  end
96
194
  end
97
195
 
98
196
  def add_rspec
99
- client.on "--[no-]rspec", "Add RSpec." do |value|
100
- options[:build_rspec] = value
197
+ client.on(
198
+ "--[no-]rspec",
199
+ "Add RSpec gem. #{default __method__}."
200
+ ) do |value|
201
+ configuration.build_rspec = value
101
202
  end
102
203
  end
103
204
 
104
205
  def add_rubocop
105
- client.on "--[no-]rubocop", "Add Rubocop." do |value|
106
- options[:build_rubocop] = value
206
+ client.on(
207
+ "--[no-]rubocop",
208
+ "Add Rubocop gems. #{default __method__}."
209
+ ) do |value|
210
+ configuration.build_rubocop = value
107
211
  end
108
212
  end
109
213
 
110
- def add_ruby_critic
111
- client.on "--[no-]ruby_critic", "Add RubyCritic." do |value|
112
- options[:build_ruby_critic] = value
214
+ def add_setup
215
+ client.on(
216
+ "--[no-]setup",
217
+ "Add setup script. #{default __method__}."
218
+ ) do |value|
219
+ configuration.build_setup = value
113
220
  end
114
221
  end
115
222
 
116
- def add_setup
117
- client.on "--[no-]setup", "Add setup script." do |value|
118
- options[:build_setup] = value
223
+ def add_simple_cov
224
+ client.on(
225
+ "--[no-]simple_cov",
226
+ "Add SimpleCov gem. #{default __method__}."
227
+ ) do |value|
228
+ configuration.build_simple_cov = value
119
229
  end
120
230
  end
121
231
 
122
- def add_simple_cov
123
- client.on "--[no-]simple_cov", "Add SimpleCov." do |value|
124
- options[:build_simple_cov] = value
232
+ def add_zeitwerk
233
+ client.on(
234
+ "--[no-]zeitwerk",
235
+ "Add Zeitwerk gem. #{default __method__}."
236
+ ) do |value|
237
+ configuration.build_zeitwerk = value
125
238
  end
126
239
  end
240
+
241
+ def default option
242
+ option.to_s
243
+ .sub("add_", "build_")
244
+ .then { |attribute| configuration.public_send attribute }
245
+ .then { |boolean| boolean ? colorizer.green(boolean) : colorizer.red(boolean) }
246
+ .then { |colored_boolean| "Default: #{colored_boolean}" }
247
+ end
248
+
249
+ def configuration = container[__method__]
250
+
251
+ def colorizer = container[__method__]
127
252
  end
128
253
  end
129
254
  end
@@ -1,17 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rubysmith/identity"
4
+ require "refinements/structs"
4
5
 
5
6
  module Rubysmith
6
7
  module CLI
7
8
  module Parsers
8
9
  # Handles parsing of Command Line Interface (CLI) core options.
9
10
  class Core
10
- def self.call(options: {}, client: CLIENT) = new(options: options, client: client).call
11
+ using Refinements::Structs
11
12
 
12
- def initialize options: {}, client: CLIENT
13
- @options = options
13
+ def self.call(...) = new(...).call
14
+
15
+ def initialize client: CLIENT, container: Container
14
16
  @client = client
17
+ @container = container
15
18
  end
16
19
 
17
20
  def call arguments = []
@@ -23,7 +26,7 @@ module Rubysmith
23
26
 
24
27
  private
25
28
 
26
- attr_reader :options, :client
29
+ attr_reader :client, :container
27
30
 
28
31
  def collate = private_methods.sort.grep(/add_/).each { |method| __send__ method }
29
32
 
@@ -32,27 +35,29 @@ module Rubysmith
32
35
  "--config ACTION",
33
36
  %i[edit view],
34
37
  "Manage gem configuration: edit or view." do |action|
35
- options[:config] = action
38
+ configuration.action_config = action
36
39
  end
37
40
  end
38
41
 
39
42
  def add_build
40
- client.on "-b", "--build NAME [options]", "Build new project." do |value|
41
- options[:build] = value
43
+ client.on "-b", "--build NAME [options]", "Build new project." do |name|
44
+ configuration.merge! action_build: true, project_name: name
42
45
  end
43
46
  end
44
47
 
45
48
  def add_version
46
49
  client.on "-v", "--version", "Show gem version." do
47
- options[:version] = Identity::VERSION_LABEL
50
+ configuration.action_version = true
48
51
  end
49
52
  end
50
53
 
51
54
  def add_help
52
55
  client.on "-h", "--help", "Show this message." do
53
- options[:help] = true
56
+ configuration.action_help = true
54
57
  end
55
58
  end
59
+
60
+ def configuration = container[__method__]
56
61
  end
57
62
  end
58
63
  end
@@ -1,57 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "refinements/hashes"
4
-
5
3
  module Rubysmith
6
4
  module CLI
7
5
  # The main Command Line Interface (CLI) object.
8
6
  class Shell
9
- using Refinements::Hashes
10
-
11
- PROCESSORS = {
12
- config: Processors::Config.new,
13
- build_minimum: Processors::Build.with_minimum,
14
- build_maximum: Processors::Build.new
15
- }.freeze
7
+ ACTIONS = {config: Actions::Config.new, build: Actions::Build.new}.freeze
16
8
 
17
- def initialize parser: Parsers::Assembler.new, processors: PROCESSORS
9
+ def initialize parser: Parsers::Assembler.new, actions: ACTIONS, container: Container
18
10
  @parser = parser
19
- @processors = processors
11
+ @actions = actions
12
+ @container = container
20
13
  end
21
14
 
22
15
  def call arguments = []
23
- parse arguments
24
-
25
- case options
26
- in config: Symbol => action then process_config action
27
- in build_minimum: true then process_build :build_minimum, options
28
- in build: then process_build :build_maximum, options
29
- in version: String => version then puts version
30
- in help: then usage
16
+ case parse arguments
17
+ in action_config: Symbol => action then config action
18
+ in action_build: true then build
19
+ in action_version: true then logger.info configuration.version
31
20
  else usage
32
21
  end
33
22
  end
34
23
 
35
24
  private
36
25
 
37
- attr_reader :parser, :processors
26
+ attr_reader :parser, :actions, :container
38
27
 
39
28
  def parse arguments = []
40
29
  parser.call arguments
41
30
  rescue StandardError => error
42
- puts error.message
31
+ logger.error error.message
43
32
  end
44
33
 
45
- def process_config(action) = processors.fetch(:config).call(action)
34
+ def config(action) = actions.fetch(__method__).call(action)
46
35
 
47
- def process_build kind, settings
48
- processors.fetch(kind).call settings.transform_keys(build: :project_name)
49
- .merge(now: Time.now)
50
- end
36
+ def build = actions.fetch(__method__).call
37
+
38
+ def usage = logger.unknown(parser.to_s)
51
39
 
52
- def options = parser.to_h
40
+ def configuration = container[__method__]
53
41
 
54
- def usage = puts(parser.to_s)
42
+ def logger = container[__method__]
55
43
  end
56
44
  end
57
45
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry-container"
4
+ require "logger"
5
+ require "pastel"
6
+
7
+ module Rubysmith
8
+ # Provides a global gem container for injection into other objects.
9
+ module Container
10
+ extend Dry::Container::Mixin
11
+
12
+ register(:configuration, memoize: true) { CLI::Configuration::Loader.call }
13
+ register(:colorizer) { Pastel.new enabled: $stdout.tty? }
14
+ register(:kernel) { Kernel }
15
+
16
+ register :log_colors do
17
+ {
18
+ "DEBUG" => self[:colorizer].white.detach,
19
+ "INFO" => self[:colorizer].green.detach,
20
+ "WARN" => self[:colorizer].yellow.detach,
21
+ "ERROR" => self[:colorizer].red.detach,
22
+ "FATAL" => self[:colorizer].white.bold.on_red.detach,
23
+ "ANY" => self[:colorizer].white.bold.detach
24
+ }
25
+ end
26
+
27
+ register :logger do
28
+ Logger.new $stdout,
29
+ level: Logger.const_get(ENV.fetch("LOG_LEVEL", "INFO")),
30
+ formatter: (
31
+ lambda do |severity, _at, _name, message|
32
+ self[:log_colors][severity].call "#{message}\n"
33
+ end
34
+ )
35
+ end
36
+ end
37
+ end
@@ -4,8 +4,8 @@ module Rubysmith
4
4
  module Identity
5
5
  NAME = "rubysmith"
6
6
  LABEL = "Rubysmith"
7
- VERSION = "0.10.0"
8
- VERSION_LABEL = "#{LABEL} #{VERSION}"
7
+ VERSION = "0.14.0"
8
+ VERSION_LABEL = "#{LABEL} #{VERSION}".freeze
9
9
  SUMMARY = "A command line interface for smithing Ruby projects."
10
10
  end
11
11
  end
@@ -21,7 +21,7 @@ module Rubysmith
21
21
  attr_accessor :buffer
22
22
  attr_reader :configuration, :scope, :client
23
23
 
24
- def namespace = self.buffer = scope.call(yield)
24
+ def namespace = self.buffer = block_given? ? scope.call(yield) : buffer + scope.call
25
25
  end
26
26
  end
27
27
  end
@@ -14,7 +14,7 @@ module Rubysmith
14
14
  @depth = namespace.scan("::").length
15
15
  end
16
16
 
17
- def call(content) = "#{prefix}#{body content}#{suffix.chomp}"
17
+ def call(content = nil) = "#{prefix}#{body content}#{suffix}"
18
18
 
19
19
  private
20
20
 
@@ -28,7 +28,7 @@ module Rubysmith
28
28
 
29
29
  # :reek:FeatureEnvy
30
30
  def body content
31
- content.lstrip.split("\n").reduce "" do |snippet, line|
31
+ String(content).lstrip.split("\n").reduce "" do |snippet, line|
32
32
  next "#{snippet}\n" if line.blank?
33
33
 
34
34
  "#{snippet}#{line.gsub(/^\s{2}/, "").indent depth + 1}\n"
@@ -0,0 +1,31 @@
1
+ version: 2.1
2
+ jobs:
3
+ build:
4
+ working_directory: ~/project
5
+ docker:
6
+ - image: bkuhlmann/alpine-ruby:latest
7
+ steps:
8
+ - checkout
9
+
10
+ - restore_cache:
11
+ name: Bundler Restore
12
+ keys:
13
+ - gem-cache-{{.Branch}}-{{checksum "Gemfile.lock"}}
14
+ - gem-cache-
15
+
16
+ - run:
17
+ name: Bundler Install
18
+ command: |
19
+ gem update --system
20
+ bundle config set path "vendor/bundle"
21
+ bundle install
22
+
23
+ - save_cache:
24
+ name: Bundler Store
25
+ key: gem-cache-{{.Branch}}-{{checksum "Gemfile.lock"}}
26
+ paths:
27
+ - vendor/bundle
28
+
29
+ - run:
30
+ name: Build
31
+ command: bundle exec rake
@@ -0,0 +1,14 @@
1
+ ## Overview
2
+ <!-- Required. Describe, briefly, the behavior experienced. -->
3
+
4
+ ## Screenshots/Screencasts
5
+ <!-- Optional. Attach screenshot(s) and/or screencast(s) that demo the behavior. -->
6
+
7
+ ## Steps to Recreate
8
+ <!-- Required. List exact steps (numbered list) to reproduce errant behavior. -->
9
+
10
+ ## Desired Behavior
11
+ <!-- Required. Describe the behavior you'd like to see or your idea of a proposed solution. -->
12
+
13
+ ## Environment
14
+ <!-- Required. What is your operating system, software version(s), etc. -->
@@ -0,0 +1,11 @@
1
+ ## Overview
2
+ <!-- Required. Why is this important/necessary and what is the overarching architecture. -->
3
+
4
+ ## Screenshots/Screencasts
5
+ <!-- Optional. Provide supporting image/video. -->
6
+
7
+ ## Details
8
+ <!-- Optional. List the key features/highlights as bullet points. -->
9
+
10
+ ## Notes
11
+ <!-- Optional. List additional notes/references as bullet points. -->