gemsmith 15.5.0 → 16.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/LICENSE.adoc +207 -155
  4. data/README.adoc +177 -189
  5. data/exe/gemsmith +6 -0
  6. data/gemsmith.gemspec +41 -0
  7. data/lib/gemsmith/builders/bundler.rb +34 -0
  8. data/lib/gemsmith/builders/cli.rb +86 -0
  9. data/lib/gemsmith/builders/git/commit.rb +46 -0
  10. data/lib/gemsmith/builders/git/ignore.rb +37 -0
  11. data/lib/gemsmith/builders/rspec/helper.rb +47 -0
  12. data/lib/gemsmith/builders/specification.rb +35 -0
  13. data/lib/gemsmith/cli/actions/build.rb +53 -0
  14. data/lib/gemsmith/cli/actions/config.rb +35 -0
  15. data/lib/gemsmith/cli/actions/edit.rb +38 -0
  16. data/lib/gemsmith/cli/actions/install.rb +36 -0
  17. data/lib/gemsmith/cli/actions/publish.rb +36 -0
  18. data/lib/gemsmith/cli/actions/view.rb +38 -0
  19. data/lib/gemsmith/cli/parser.rb +33 -0
  20. data/lib/gemsmith/cli/parsers/build.rb +54 -0
  21. data/lib/gemsmith/cli/parsers/core.rb +94 -0
  22. data/lib/gemsmith/cli/shell.rb +66 -0
  23. data/lib/gemsmith/configuration/enhancers/template_root.rb +20 -0
  24. data/lib/gemsmith/configuration/loader.rb +50 -0
  25. data/lib/gemsmith/container.rb +21 -0
  26. data/lib/gemsmith/gems/finder.rb +21 -0
  27. data/lib/gemsmith/gems/loader.rb +21 -0
  28. data/lib/gemsmith/gems/picker.rb +43 -0
  29. data/lib/gemsmith/gems/presenter.rb +50 -0
  30. data/lib/gemsmith/templates/%project_name%/%project_name%.gemspec.erb +49 -0
  31. data/lib/gemsmith/templates/%project_name%/exe/%project_name%.erb +5 -0
  32. data/lib/gemsmith/templates/%project_name%/lib/%project_path%/cli/actions/config.rb.erb +35 -0
  33. data/lib/gemsmith/templates/%project_name%/lib/%project_path%/cli/parser.rb.erb +31 -0
  34. data/lib/gemsmith/templates/%project_name%/lib/%project_path%/cli/parsers/core.rb.erb +54 -0
  35. data/lib/gemsmith/templates/%project_name%/lib/%project_path%/cli/shell.rb.erb +38 -0
  36. data/lib/gemsmith/templates/%project_name%/lib/%project_path%/configuration/content.rb.erb +18 -0
  37. data/lib/gemsmith/templates/%project_name%/lib/%project_path%/configuration/defaults.yml.erb +0 -0
  38. data/lib/gemsmith/templates/%project_name%/lib/%project_path%/configuration/loader.rb.erb +33 -0
  39. data/lib/gemsmith/templates/%project_name%/lib/%project_path%/container.rb.erb +35 -0
  40. data/lib/gemsmith/templates/{%gem_name%/lib/%gem_path%/identity.rb.tt → %project_name%/lib/%project_path%/identity.rb.erb} +1 -1
  41. data/lib/gemsmith/templates/%project_name%/spec/lib/%project_path%/cli/actions/config_spec.rb.erb +24 -0
  42. data/lib/gemsmith/templates/%project_name%/spec/lib/%project_path%/cli/parser_spec.rb.erb +25 -0
  43. data/lib/gemsmith/templates/%project_name%/spec/lib/%project_path%/cli/parsers/core_spec.rb.erb +53 -0
  44. data/lib/gemsmith/templates/%project_name%/spec/lib/%project_path%/cli/shell_spec.rb.erb +43 -0
  45. data/lib/gemsmith/templates/%project_name%/spec/lib/%project_path%/configuration/content_spec.rb.erb +15 -0
  46. data/lib/gemsmith/templates/%project_name%/spec/lib/%project_path%/configuration/loader_spec.rb.erb +29 -0
  47. data/lib/gemsmith/templates/%project_name%/spec/support/shared_contexts/application_container.rb.erb +22 -0
  48. data/lib/gemsmith/templates/%project_name%/spec/support/shared_examples/a_parser.rb.erb +7 -0
  49. data/lib/gemsmith/tools/cleaner.rb +29 -0
  50. data/lib/gemsmith/tools/editor.rb +30 -0
  51. data/lib/gemsmith/tools/installer.rb +39 -0
  52. data/lib/gemsmith/tools/packager.rb +33 -0
  53. data/lib/gemsmith/tools/publisher.rb +34 -0
  54. data/lib/gemsmith/tools/pusher.rb +36 -0
  55. data/lib/gemsmith/tools/validator.rb +28 -0
  56. data/lib/gemsmith/tools/versioner.rb +43 -0
  57. data/lib/gemsmith/tools/viewer.rb +28 -0
  58. data/lib/gemsmith.rb +5 -3
  59. data.tar.gz.sig +0 -0
  60. metadata +87 -115
  61. metadata.gz.sig +0 -0
  62. data/bin/gemsmith +0 -9
  63. data/lib/gemsmith/authenticators/basic.rb +0 -28
  64. data/lib/gemsmith/authenticators/ruby_gems.rb +0 -41
  65. data/lib/gemsmith/cli.rb +0 -259
  66. data/lib/gemsmith/credentials.rb +0 -82
  67. data/lib/gemsmith/errors/base.rb +0 -9
  68. data/lib/gemsmith/errors/requirement_conversion.rb +0 -9
  69. data/lib/gemsmith/errors/requirement_operator.rb +0 -9
  70. data/lib/gemsmith/errors/specification.rb +0 -9
  71. data/lib/gemsmith/gem/inspector.rb +0 -30
  72. data/lib/gemsmith/gem/module_formatter.rb +0 -50
  73. data/lib/gemsmith/gem/requirement.rb +0 -55
  74. data/lib/gemsmith/gem/specification.rb +0 -74
  75. data/lib/gemsmith/generators/base.rb +0 -46
  76. data/lib/gemsmith/generators/bundler.rb +0 -19
  77. data/lib/gemsmith/generators/bundler_audit.rb +0 -15
  78. data/lib/gemsmith/generators/circle_ci.rb +0 -14
  79. data/lib/gemsmith/generators/cli.rb +0 -17
  80. data/lib/gemsmith/generators/documentation.rb +0 -36
  81. data/lib/gemsmith/generators/engine.rb +0 -77
  82. data/lib/gemsmith/generators/gem.rb +0 -29
  83. data/lib/gemsmith/generators/git.rb +0 -45
  84. data/lib/gemsmith/generators/git_hub.rb +0 -15
  85. data/lib/gemsmith/generators/git_lint.rb +0 -14
  86. data/lib/gemsmith/generators/guard.rb +0 -14
  87. data/lib/gemsmith/generators/pragma.rb +0 -49
  88. data/lib/gemsmith/generators/rake.rb +0 -76
  89. data/lib/gemsmith/generators/reek.rb +0 -17
  90. data/lib/gemsmith/generators/rspec.rb +0 -39
  91. data/lib/gemsmith/generators/rubocop.rb +0 -18
  92. data/lib/gemsmith/generators/ruby.rb +0 -12
  93. data/lib/gemsmith/helpers/cli.rb +0 -59
  94. data/lib/gemsmith/helpers/template.rb +0 -30
  95. data/lib/gemsmith/identity.rb +0 -12
  96. data/lib/gemsmith/rake/builder.rb +0 -57
  97. data/lib/gemsmith/rake/publisher.rb +0 -100
  98. data/lib/gemsmith/rake/setup.rb +0 -4
  99. data/lib/gemsmith/rake/tasks.rb +0 -83
  100. data/lib/gemsmith/templates/%gem_name%/%gem_name%.gemspec.tt +0 -44
  101. data/lib/gemsmith/templates/%gem_name%/.circleci/config.yml.tt +0 -31
  102. data/lib/gemsmith/templates/%gem_name%/.github/ISSUE_TEMPLATE.md.tt +0 -14
  103. data/lib/gemsmith/templates/%gem_name%/.github/PULL_REQUEST_TEMPLATE.md.tt +0 -11
  104. data/lib/gemsmith/templates/%gem_name%/.gitignore.tt +0 -6
  105. data/lib/gemsmith/templates/%gem_name%/.reek.yml.tt +0 -6
  106. data/lib/gemsmith/templates/%gem_name%/.rubocop.yml.tt +0 -15
  107. data/lib/gemsmith/templates/%gem_name%/.ruby-version.tt +0 -1
  108. data/lib/gemsmith/templates/%gem_name%/CHANGES.md.tt +0 -3
  109. data/lib/gemsmith/templates/%gem_name%/CODE_OF_CONDUCT.md.tt +0 -66
  110. data/lib/gemsmith/templates/%gem_name%/CONTRIBUTING.md.tt +0 -22
  111. data/lib/gemsmith/templates/%gem_name%/Gemfile.tt +0 -47
  112. data/lib/gemsmith/templates/%gem_name%/Guardfile.tt +0 -21
  113. data/lib/gemsmith/templates/%gem_name%/LICENSE.md.tt +0 -20
  114. data/lib/gemsmith/templates/%gem_name%/README.md.tt +0 -93
  115. data/lib/gemsmith/templates/%gem_name%/Rakefile.tt +0 -12
  116. data/lib/gemsmith/templates/%gem_name%/bin/%gem_name%.tt +0 -8
  117. data/lib/gemsmith/templates/%gem_name%/bin/console.tt +0 -10
  118. data/lib/gemsmith/templates/%gem_name%/bin/setup.tt +0 -8
  119. data/lib/gemsmith/templates/%gem_name%/lib/%gem_path%/cli.rb.tt +0 -61
  120. data/lib/gemsmith/templates/%gem_name%/lib/%gem_path%/engine.rb.tt +0 -6
  121. data/lib/gemsmith/templates/%gem_name%/lib/%gem_path%.rb.tt +0 -7
  122. data/lib/gemsmith/templates/%gem_name%/lib/generators/%gem_path%/install/USAGE.tt +0 -8
  123. data/lib/gemsmith/templates/%gem_name%/lib/generators/%gem_path%/install/install_generator.rb.tt +0 -12
  124. data/lib/gemsmith/templates/%gem_name%/lib/generators/%gem_path%/upgrade/USAGE.tt +0 -8
  125. data/lib/gemsmith/templates/%gem_name%/lib/generators/%gem_path%/upgrade/upgrade_generator.rb.tt +0 -10
  126. data/lib/gemsmith/templates/%gem_name%/spec/lib/%gem_path%/cli_spec.rb.tt +0 -81
  127. data/lib/gemsmith/templates/%gem_name%/spec/rails_helper.rb.tt +0 -14
  128. data/lib/gemsmith/templates/%gem_name%/spec/spec_helper.rb.tt +0 -37
  129. data/lib/gemsmith/templates/%gem_name%/spec/support/shared_contexts/temp_dir.rb.tt +0 -9
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gemsmith
4
+ module Builders
5
+ module Git
6
+ # Builds project skeleton initial Git commit message.
7
+ class Commit
8
+ def self.call(...) = new(...).call
9
+
10
+ def initialize configuration, builder: Rubysmith::Builder, container: Container
11
+ @configuration = configuration
12
+ @builder = builder
13
+ @container = container
14
+ end
15
+
16
+ def call
17
+ return configuration unless configuration.build_git
18
+
19
+ builder.call(configuration)
20
+ .run("git add .", chdir: project_name)
21
+ .run(
22
+ %(git commit --all --message "Added project skeleton" --message "#{body}"),
23
+ chdir: project_name
24
+ )
25
+
26
+ configuration
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :configuration, :builder, :container
32
+
33
+ def body
34
+ <<~CONTENT
35
+ Generated with [#{specification.label}](#{specification.homepage_url})
36
+ #{specification.version}.
37
+ CONTENT
38
+ end
39
+
40
+ def project_name = configuration.project_name
41
+
42
+ def specification = container[__method__]
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "refinements/structs"
4
+
5
+ module Gemsmith
6
+ module Builders
7
+ module Git
8
+ # Builds project skeleton Git ignore.
9
+ class Ignore
10
+ using Refinements::Structs
11
+
12
+ def self.call(...) = new(...).call
13
+
14
+ def initialize configuration, builder: Rubysmith::Builder
15
+ @configuration = configuration
16
+ @builder = builder
17
+ end
18
+
19
+ def call
20
+ return configuration unless configuration.build_git
21
+
22
+ builder.call(configuration.merge(template_path: "%project_name%/.gitignore.erb"))
23
+ .touch
24
+ .prepend("*.gem\n")
25
+ .insert_before("tmp\n", "Gemfile.lock\n")
26
+ .insert_before("tmp\n", "pkg\n")
27
+
28
+ configuration
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :configuration, :builder
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "refinements/structs"
4
+
5
+ module Gemsmith
6
+ module Builders
7
+ module RSpec
8
+ # Builds RSpec spec helper for project skeleton.
9
+ class Helper
10
+ using Refinements::Structs
11
+
12
+ def self.call(...) = new(...).call
13
+
14
+ def initialize configuration, builder: Rubysmith::Builder
15
+ @configuration = configuration
16
+ @builder = builder
17
+ end
18
+
19
+ def call
20
+ return configuration unless configuration.build_rspec && configuration.build_cli
21
+
22
+ update_spec_helper
23
+ render_shared_example
24
+ configuration
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :configuration, :builder
30
+
31
+ def update_spec_helper
32
+ builder.call(configuration.merge(template_path: "%project_name%/spec/spec_helper.rb.erb"))
33
+ .touch
34
+ .insert_after(
35
+ %r(support/shared_contexts),
36
+ %(Pathname.require_tree __dir__, "support/shared_examples/**/*.rb"\n)
37
+ )
38
+ end
39
+
40
+ def render_shared_example
41
+ path = "%project_name%/spec/support/shared_examples/a_parser.rb.erb"
42
+ builder.call(configuration.merge(template_path: path)).render
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "refinements/structs"
4
+
5
+ module Gemsmith
6
+ module Builders
7
+ # Builds project skeleton gem specification for use by RubyGems.
8
+ class Specification
9
+ using Refinements::Structs
10
+
11
+ def self.call(...) = new(...).call
12
+
13
+ def initialize configuration, builder: Rubysmith::Builder
14
+ @configuration = configuration
15
+ @builder = builder
16
+ end
17
+
18
+ def call
19
+ config = configuration.merge template_path: "%project_name%/%project_name%.gemspec.erb"
20
+
21
+ builder.call(config)
22
+ .render
23
+ .replace(" \n", "")
24
+ .replace(" spec", " spec")
25
+ .replace(/\}\s+s/m, "}\n\n s")
26
+
27
+ configuration
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :configuration, :builder
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gemsmith
4
+ module CLI
5
+ module Actions
6
+ # Handles the build action.
7
+ class Build
8
+ # Order is important.
9
+ BUILDERS = [
10
+ Rubysmith::Builders::Core,
11
+ Rubysmith::Builders::Version,
12
+ Builders::Specification,
13
+ Rubysmith::Builders::Documentation::Readme,
14
+ Rubysmith::Builders::Documentation::Citation,
15
+ Rubysmith::Builders::Documentation::License,
16
+ Rubysmith::Builders::Documentation::Version,
17
+ Rubysmith::Builders::Git::Setup,
18
+ Rubysmith::Builders::Git::Ignore,
19
+ Builders::Git::Ignore,
20
+ Rubysmith::Builders::Bundler,
21
+ Builders::Bundler,
22
+ Builders::CLI,
23
+ Rubysmith::Builders::Rake,
24
+ Rubysmith::Builders::Console,
25
+ Rubysmith::Builders::CircleCI,
26
+ Rubysmith::Builders::Setup,
27
+ Rubysmith::Builders::GitHub,
28
+ Rubysmith::Builders::Guard,
29
+ Rubysmith::Builders::Reek,
30
+ Rubysmith::Builders::RSpec::Context,
31
+ Rubysmith::Builders::RSpec::Helper,
32
+ Builders::RSpec::Helper,
33
+ Rubysmith::Builders::Rubocop,
34
+ Rubysmith::Extensions::Bundler,
35
+ Rubysmith::Extensions::Pragmater,
36
+ Rubysmith::Extensions::Tocer,
37
+ Rubysmith::Extensions::Rubocop,
38
+ Builders::Git::Commit
39
+ ].freeze
40
+
41
+ def initialize builders: BUILDERS
42
+ @builders = builders
43
+ end
44
+
45
+ def call(configuration) = builders.each { |builder| builder.call configuration }
46
+
47
+ private
48
+
49
+ attr_reader :configuration, :builders
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gemsmith
4
+ module CLI
5
+ module Actions
6
+ # Handles the config action.
7
+ class Config
8
+ def initialize client: Configuration::Loader::CLIENT, container: Container
9
+ @client = client
10
+ @container = container
11
+ end
12
+
13
+ def call selection
14
+ case selection
15
+ when :edit then edit
16
+ when :view then view
17
+ else logger.error { "Invalid configuration selection: #{selection}." }
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :client, :container
24
+
25
+ def edit = kernel.system("$EDITOR #{client.current}")
26
+
27
+ def view = kernel.system("cat #{client.current}")
28
+
29
+ def kernel = container[__method__]
30
+
31
+ def logger = container[__method__]
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/monads"
4
+
5
+ module Gemsmith
6
+ module CLI
7
+ module Actions
8
+ # Handles the edit action for editing an installed gem.
9
+ class Edit
10
+ include Dry::Monads[:result]
11
+
12
+ def initialize picker: Gems::Picker, editor: Tools::Editor.new, container: Container
13
+ @picker = picker
14
+ @editor = editor
15
+ @container = container
16
+ end
17
+
18
+ def call gem_name
19
+ case picker.call(gem_name).bind { |spec| editor.call spec }
20
+ in Success(spec) then logger.info { "Editing: #{spec.named_version}." }
21
+ in Failure(message) then error { message }
22
+ else error { "Unable to handle edit action." }
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :picker, :editor, :container
29
+
30
+ def error(&) = logger.error(&)
31
+
32
+ def kernel = container[__method__]
33
+
34
+ def logger = container[__method__]
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/monads"
4
+
5
+ module Gemsmith
6
+ module CLI
7
+ module Actions
8
+ # Handles the install action.
9
+ class Install
10
+ include Dry::Monads[:result]
11
+
12
+ def initialize installer: Tools::Installer.new, loader: Gems::Loader, container: Container
13
+ @installer = installer
14
+ @loader = loader
15
+ @container = container
16
+ end
17
+
18
+ def call configuration
19
+ case installer.call loader.call("#{configuration.project_name}.gemspec")
20
+ in Success(spec) then logger.info { "Installed: #{spec.package_name}." }
21
+ in Failure(message) then error { message }
22
+ else error { "Unable to handle install action." }
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :installer, :loader, :container
29
+
30
+ def error(&) = logger.error(&)
31
+
32
+ def logger = container[__method__]
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/monads"
4
+
5
+ module Gemsmith
6
+ module CLI
7
+ module Actions
8
+ # Handles the publish action.
9
+ class Publish
10
+ include Dry::Monads[:result]
11
+
12
+ def initialize publisher: Tools::Publisher.new, loader: Gems::Loader, container: Container
13
+ @publisher = publisher
14
+ @loader = loader
15
+ @container = container
16
+ end
17
+
18
+ def call configuration
19
+ case publisher.call loader.call("#{configuration.project_name}.gemspec")
20
+ in Success(spec) then logger.info { "Published: #{spec.package_name}." }
21
+ in Failure(message) then error { message }
22
+ else error { "Unable to handle publish action." }
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :publisher, :loader, :container
29
+
30
+ def error(&) = logger.error(&)
31
+
32
+ def logger = container[__method__]
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/monads"
4
+
5
+ module Gemsmith
6
+ module CLI
7
+ module Actions
8
+ # Handles the view action for viewing an installed gem in default browser.
9
+ class View
10
+ include Dry::Monads[:result]
11
+
12
+ def initialize picker: Gems::Picker, viewer: Tools::Viewer.new, container: Container
13
+ @picker = picker
14
+ @viewer = viewer
15
+ @container = container
16
+ end
17
+
18
+ def call gem_name
19
+ case picker.call(gem_name).bind { |spec| viewer.call spec }
20
+ in Success(spec) then logger.info { "Viewing: #{spec.named_version}." }
21
+ in Failure(message) then error { message }
22
+ else error { "Unable to handle view action." }
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :picker, :viewer, :container
29
+
30
+ def error(&) = logger.error(&)
31
+
32
+ def kernel = container[__method__]
33
+
34
+ def logger = container[__method__]
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "optparse"
4
+
5
+ module Gemsmith
6
+ module CLI
7
+ # Assembles and parses all Command Line Interface (CLI) options.
8
+ class Parser
9
+ CLIENT = OptionParser.new nil, 40, " "
10
+
11
+ # Order is important.
12
+ SECTIONS = [Parsers::Core, Rubysmith::CLI::Parsers::Build, Parsers::Build].freeze
13
+
14
+ def initialize sections: SECTIONS, client: CLIENT, container: Container
15
+ @sections = sections
16
+ @client = client
17
+ @configuration = container[:configuration].dup
18
+ end
19
+
20
+ def call arguments = []
21
+ sections.each { |section| section.call configuration, client: }
22
+ client.parse arguments
23
+ configuration.freeze
24
+ end
25
+
26
+ def to_s = client.to_s
27
+
28
+ private
29
+
30
+ attr_reader :sections, :client, :configuration
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "refinements/structs"
4
+
5
+ module Gemsmith
6
+ module CLI
7
+ module Parsers
8
+ # Handles parsing of Command Line Interface (CLI) build options.
9
+ class Build
10
+ using Refinements::Structs
11
+
12
+ def self.call(...) = new(...).call
13
+
14
+ def initialize configuration = Container[:configuration],
15
+ client: Parser::CLIENT,
16
+ container: Container
17
+ @configuration = configuration
18
+ @client = client
19
+ @container = container
20
+ end
21
+
22
+ def call arguments = []
23
+ add_cli
24
+ client.parse arguments
25
+ configuration
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :configuration, :client, :container
31
+
32
+ def add_cli
33
+ client.on(
34
+ "--[no-]cli",
35
+ "Add command line interface. #{default __method__}."
36
+ ) do |value|
37
+ configuration.merge! build_refinements: value, build_zeitwerk: value if value
38
+ configuration.merge! build_cli: value
39
+ end
40
+ end
41
+
42
+ def default option
43
+ option.to_s
44
+ .sub("add_", "build_")
45
+ .then { |attribute| configuration.public_send attribute }
46
+ .then { |boolean| boolean ? colorizer.green(boolean) : colorizer.red(boolean) }
47
+ .then { |colored_boolean| "Default: #{colored_boolean}" }
48
+ end
49
+
50
+ def colorizer = container[__method__]
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ require "refinements/structs"
5
+
6
+ module Gemsmith
7
+ module CLI
8
+ module Parsers
9
+ # Handles parsing of Command Line Interface (CLI) core options.
10
+ class Core
11
+ using Refinements::Structs
12
+
13
+ def self.call(...) = new(...).call
14
+
15
+ def initialize configuration = Container[:configuration],
16
+ client: Parser::CLIENT,
17
+ container: Container
18
+ @configuration = configuration
19
+ @client = client
20
+ @container = container
21
+ end
22
+
23
+ def call arguments = []
24
+ client.banner = specification.labeled_summary
25
+ client.separator "\nUSAGE:\n"
26
+ collate
27
+ client.parse arguments
28
+ configuration
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :configuration, :client, :container
34
+
35
+ def collate = private_methods.sort.grep(/add_/).each { |method| __send__ method }
36
+
37
+ def add_config
38
+ client.on "-c",
39
+ "--config ACTION",
40
+ %i[edit view],
41
+ "Manage gem configuration: edit or view." do |action|
42
+ configuration.merge! action_config: action
43
+ end
44
+ end
45
+
46
+ def add_build
47
+ client.on "-b", "--build NAME [options]", "Build new project." do |name|
48
+ configuration.merge! action_build: true, project_name: name
49
+ end
50
+ end
51
+
52
+ def add_edit
53
+ client.on "--edit GEM", "Edit installed gem in default editor." do |gem_name|
54
+ configuration.merge! action_edit: gem_name
55
+ end
56
+ end
57
+
58
+ def add_install
59
+ client.on "-i", "--install [NAME]", "Install gem for local development." do |name|
60
+ configuration.merge! action_install: true,
61
+ project_name: name || Pathname.pwd.basename.to_s
62
+ end
63
+ end
64
+
65
+ def add_publish
66
+ client.on "-p", "--publish [NAME]", "Publish gem to remote gem server." do |name|
67
+ configuration.merge! action_publish: true,
68
+ project_name: name || Pathname.pwd.basename.to_s
69
+ end
70
+ end
71
+
72
+ def add_view
73
+ client.on "--view GEM", "View installed gem in default browser." do |gem_name|
74
+ configuration.merge! action_view: gem_name
75
+ end
76
+ end
77
+
78
+ def add_version
79
+ client.on "-v", "--version", "Show gem version." do
80
+ configuration.merge! action_version: true
81
+ end
82
+ end
83
+
84
+ def add_help
85
+ client.on "-h", "--help", "Show this message." do
86
+ configuration.merge! action_help: true
87
+ end
88
+ end
89
+
90
+ def specification = container[__method__]
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gemsmith
4
+ module CLI
5
+ # The main Command Line Interface (CLI) object.
6
+ class Shell
7
+ ACTIONS = {
8
+ config: Actions::Config.new,
9
+ build: Actions::Build.new,
10
+ install: Actions::Install.new,
11
+ publish: Actions::Publish.new,
12
+ edit: Actions::Edit.new,
13
+ view: Actions::View.new
14
+ }.freeze
15
+
16
+ def initialize parser: Parser.new, actions: ACTIONS, container: Container
17
+ @parser = parser
18
+ @actions = actions
19
+ @container = container
20
+ end
21
+
22
+ def call arguments = []
23
+ perform parser.call(arguments)
24
+ rescue OptionParser::ParseError => error
25
+ logger.error { error.message }
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :parser, :actions, :container
31
+
32
+ def perform configuration
33
+ case configuration
34
+ in action_config: Symbol => action then config action
35
+ in action_build: true then build configuration
36
+ in action_install: true then install configuration
37
+ in action_publish: true then publish configuration
38
+ in action_edit: String => gem_name then edit gem_name
39
+ in action_view: String => gem_name then view gem_name
40
+ in action_version: true then logger.info specification.labeled_version
41
+ else usage
42
+ end
43
+ end
44
+
45
+ def config(action) = actions.fetch(__method__).call(action)
46
+
47
+ def build(configuration) = actions.fetch(__method__).call(configuration)
48
+
49
+ def install(configuration) = actions.fetch(__method__).call(configuration)
50
+
51
+ def publish(configuration) = actions.fetch(__method__).call(configuration)
52
+
53
+ def edit(gem_name) = actions.fetch(__method__).call(gem_name)
54
+
55
+ def view(gem_name) = actions.fetch(__method__).call(gem_name)
56
+
57
+ def usage = logger.unknown(parser.to_s)
58
+
59
+ def logger = container[__method__]
60
+
61
+ def specification = container[__method__]
62
+
63
+ def process = container[__method__]
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gemsmith
4
+ module Configuration
5
+ module Enhancers
6
+ # Adds gem specific roots to existing content.
7
+ class TemplateRoot
8
+ def initialize overrides = Pathname(__dir__).join("../../templates")
9
+ @overrides = Array overrides
10
+ end
11
+
12
+ def call(content) = content.add_template_roots(overrides)
13
+
14
+ private
15
+
16
+ attr_reader :overrides
17
+ end
18
+ end
19
+ end
20
+ end