cuprum-cli 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/CHANGELOG.md +34 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE +21 -0
- data/README.md +163 -0
- data/lib/cuprum/cli/argument.rb +172 -0
- data/lib/cuprum/cli/arguments/class_methods.rb +283 -0
- data/lib/cuprum/cli/arguments.rb +16 -0
- data/lib/cuprum/cli/coercion.rb +131 -0
- data/lib/cuprum/cli/command.rb +102 -0
- data/lib/cuprum/cli/commands/ci/report.rb +121 -0
- data/lib/cuprum/cli/commands/ci/rspec_command.rb +108 -0
- data/lib/cuprum/cli/commands/ci/rspec_each_command.rb +185 -0
- data/lib/cuprum/cli/commands/ci.rb +12 -0
- data/lib/cuprum/cli/commands/echo_command.rb +76 -0
- data/lib/cuprum/cli/commands/file/generate_file.rb +141 -0
- data/lib/cuprum/cli/commands/file/new_command.rb +86 -0
- data/lib/cuprum/cli/commands/file/render_erb.rb +88 -0
- data/lib/cuprum/cli/commands/file/resolve_template.rb +136 -0
- data/lib/cuprum/cli/commands/file/templates/rspec.rb.erb +14 -0
- data/lib/cuprum/cli/commands/file/templates/ruby.rb.erb +29 -0
- data/lib/cuprum/cli/commands/file/templates.rb +71 -0
- data/lib/cuprum/cli/commands/file.rb +14 -0
- data/lib/cuprum/cli/commands.rb +12 -0
- data/lib/cuprum/cli/dependencies/file_system/mock.rb +297 -0
- data/lib/cuprum/cli/dependencies/file_system.rb +247 -0
- data/lib/cuprum/cli/dependencies/standard_io/helpers.rb +138 -0
- data/lib/cuprum/cli/dependencies/standard_io/mock.rb +85 -0
- data/lib/cuprum/cli/dependencies/standard_io.rb +110 -0
- data/lib/cuprum/cli/dependencies/system_command/mock.rb +57 -0
- data/lib/cuprum/cli/dependencies/system_command.rb +147 -0
- data/lib/cuprum/cli/dependencies.rb +25 -0
- data/lib/cuprum/cli/errors/files/file_not_writeable.rb +42 -0
- data/lib/cuprum/cli/errors/files/missing_parameter.rb +71 -0
- data/lib/cuprum/cli/errors/files/missing_template.rb +36 -0
- data/lib/cuprum/cli/errors/files/template_error.rb +37 -0
- data/lib/cuprum/cli/errors/files/template_not_resolved.rb +54 -0
- data/lib/cuprum/cli/errors/files.rb +19 -0
- data/lib/cuprum/cli/errors/system_command_failure.rb +44 -0
- data/lib/cuprum/cli/errors.rb +11 -0
- data/lib/cuprum/cli/integrations/thor/arguments_parser.rb +99 -0
- data/lib/cuprum/cli/integrations/thor/registry.rb +42 -0
- data/lib/cuprum/cli/integrations/thor/task.rb +211 -0
- data/lib/cuprum/cli/integrations/thor.rb +14 -0
- data/lib/cuprum/cli/integrations.rb +8 -0
- data/lib/cuprum/cli/metadata.rb +215 -0
- data/lib/cuprum/cli/option.rb +165 -0
- data/lib/cuprum/cli/options/class_methods.rb +232 -0
- data/lib/cuprum/cli/options/quiet.rb +32 -0
- data/lib/cuprum/cli/options/verbose.rb +32 -0
- data/lib/cuprum/cli/options.rb +18 -0
- data/lib/cuprum/cli/registry.rb +141 -0
- data/lib/cuprum/cli/rspec/deferred/arguments_examples.rb +203 -0
- data/lib/cuprum/cli/rspec/deferred/ci/report_examples.rb +450 -0
- data/lib/cuprum/cli/rspec/deferred/ci.rb +8 -0
- data/lib/cuprum/cli/rspec/deferred/dependencies/file_system_examples.rb +1469 -0
- data/lib/cuprum/cli/rspec/deferred/dependencies.rb +8 -0
- data/lib/cuprum/cli/rspec/deferred/metadata_examples.rb +856 -0
- data/lib/cuprum/cli/rspec/deferred/options_examples.rb +234 -0
- data/lib/cuprum/cli/rspec/deferred/registry_examples.rb +451 -0
- data/lib/cuprum/cli/rspec/deferred.rb +8 -0
- data/lib/cuprum/cli/rspec.rb +8 -0
- data/lib/cuprum/cli/version.rb +59 -0
- data/lib/cuprum/cli.rb +47 -0
- metadata +173 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
require 'cuprum/cli/command'
|
|
6
|
+
require 'cuprum/cli/commands'
|
|
7
|
+
|
|
8
|
+
module Cuprum::Cli::Commands
|
|
9
|
+
# Outputs the arguments and options passed to the command.
|
|
10
|
+
class EchoCommand < Cuprum::Cli::Command
|
|
11
|
+
dependency :file_system
|
|
12
|
+
dependency :standard_io
|
|
13
|
+
|
|
14
|
+
description 'Outputs the arguments and options passed to the command.'
|
|
15
|
+
|
|
16
|
+
arguments :args, type: String
|
|
17
|
+
|
|
18
|
+
option :format, type: String
|
|
19
|
+
option :out, type: String
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def format_arguments_as_text
|
|
24
|
+
return '[]' if args.empty?
|
|
25
|
+
|
|
26
|
+
formatted = args.map(&:inspect).join(', ')
|
|
27
|
+
|
|
28
|
+
"[#{formatted}]"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def format_options_as_text(kwargs)
|
|
32
|
+
return '{}' if kwargs.empty?
|
|
33
|
+
|
|
34
|
+
formatted =
|
|
35
|
+
kwargs.map { |key, value| "#{key}: #{value.inspect}" }.join(', ')
|
|
36
|
+
|
|
37
|
+
"{ #{formatted} }"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def format_parameters
|
|
41
|
+
case format&.downcase
|
|
42
|
+
when 'json'
|
|
43
|
+
JSON.pretty_generate({ arguments: args, options: options.compact })
|
|
44
|
+
else
|
|
45
|
+
format_parameters_as_text
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def format_parameters_as_text
|
|
50
|
+
buffer = "#{self.class.name} called with "
|
|
51
|
+
kwargs = options.compact
|
|
52
|
+
|
|
53
|
+
return buffer << 'no parameters.' if args.empty? && kwargs.empty?
|
|
54
|
+
|
|
55
|
+
buffer <<
|
|
56
|
+
"parameters:\n" \
|
|
57
|
+
"\n Arguments: #{format_arguments_as_text}" \
|
|
58
|
+
"\n Options: #{format_options_as_text(kwargs)}" \
|
|
59
|
+
"\n"
|
|
60
|
+
|
|
61
|
+
buffer.freeze
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def process
|
|
65
|
+
formatted = format_parameters
|
|
66
|
+
|
|
67
|
+
if out
|
|
68
|
+
file_system.write(out, formatted)
|
|
69
|
+
else
|
|
70
|
+
standard_io.write_output(formatted)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
nil
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/command'
|
|
4
|
+
require 'plumbum'
|
|
5
|
+
|
|
6
|
+
require 'cuprum/cli/commands/file'
|
|
7
|
+
require 'cuprum/cli/commands/file/render_erb'
|
|
8
|
+
require 'cuprum/cli/dependencies'
|
|
9
|
+
require 'cuprum/cli/dependencies/file_system'
|
|
10
|
+
require 'cuprum/cli/errors/files/missing_template'
|
|
11
|
+
require 'cuprum/cli/options'
|
|
12
|
+
|
|
13
|
+
module Cuprum::Cli::Commands::File
|
|
14
|
+
# Utility command for generating a file from a template.
|
|
15
|
+
class GenerateFile < Cuprum::Command
|
|
16
|
+
include Plumbum::Consumer
|
|
17
|
+
prepend Plumbum::Parameters
|
|
18
|
+
include Cuprum::Cli::Dependencies::StandardIo::Helpers
|
|
19
|
+
extend Cuprum::Cli::Options::ClassMethods
|
|
20
|
+
include Cuprum::Cli::Options::Quiet
|
|
21
|
+
include Cuprum::Cli::Options::Verbose
|
|
22
|
+
|
|
23
|
+
dependency :file_system
|
|
24
|
+
dependency :standard_io
|
|
25
|
+
|
|
26
|
+
provider Cuprum::Cli::Dependencies.provider
|
|
27
|
+
|
|
28
|
+
option :directories, type: :boolean, default: true
|
|
29
|
+
option :dry_run, type: :boolean, default: false
|
|
30
|
+
option :force, type: :boolean, default: false
|
|
31
|
+
|
|
32
|
+
# @overload initialize(**options)
|
|
33
|
+
# @param options [Hash] options for initializing the command.
|
|
34
|
+
def initialize(**)
|
|
35
|
+
super()
|
|
36
|
+
|
|
37
|
+
@options = self.class.resolve_options(**)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
attr_reader :options
|
|
43
|
+
|
|
44
|
+
def check_if_file_already_exists(file_path:)
|
|
45
|
+
return unless file_system.file?(file_path)
|
|
46
|
+
return if force?
|
|
47
|
+
|
|
48
|
+
error =
|
|
49
|
+
file_not_writeable_error(file_path:, reason: 'file already exists')
|
|
50
|
+
|
|
51
|
+
failure(error)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def check_if_file_is_directory(file_path:)
|
|
55
|
+
return unless file_system.directory?(file_path)
|
|
56
|
+
|
|
57
|
+
error =
|
|
58
|
+
file_not_writeable_error(file_path:, reason: 'file is a directory')
|
|
59
|
+
|
|
60
|
+
failure(error)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def create_directory(file_path:)
|
|
64
|
+
return unless directories?
|
|
65
|
+
|
|
66
|
+
return if dry_run?
|
|
67
|
+
return if file_system.directory?(file_path)
|
|
68
|
+
|
|
69
|
+
*dir_names, _ = file_path.split(File::SEPARATOR)
|
|
70
|
+
|
|
71
|
+
return if dir_names.empty?
|
|
72
|
+
|
|
73
|
+
file_system.create_directory(
|
|
74
|
+
dir_names.join(File::SEPARATOR),
|
|
75
|
+
recursive: true
|
|
76
|
+
)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def file_not_writeable_error(**)
|
|
80
|
+
Cuprum::Cli::Errors::Files::FileNotWriteable.new(**)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def load_template(file_path:, template_path:)
|
|
84
|
+
file_system.read_file(template_path)
|
|
85
|
+
rescue Cuprum::Cli::Dependencies::FileSystem::FileNotFoundError
|
|
86
|
+
error = Cuprum::Cli::Errors::Files::MissingTemplate.new(
|
|
87
|
+
message: "unable to generate file #{file_path}",
|
|
88
|
+
template_path:
|
|
89
|
+
)
|
|
90
|
+
failure(error)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def process(file_path:, parameters:, template_path:)
|
|
94
|
+
say "Generating file #{file_path}..."
|
|
95
|
+
|
|
96
|
+
template = step { load_template(file_path:, template_path:) }
|
|
97
|
+
contents =
|
|
98
|
+
step { render_template(parameters:, template:, template_path:) }
|
|
99
|
+
|
|
100
|
+
report_file_contents(contents)
|
|
101
|
+
|
|
102
|
+
step { create_directory(file_path:) }
|
|
103
|
+
|
|
104
|
+
step { write_file(contents:, file_path:) }
|
|
105
|
+
|
|
106
|
+
file_path
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def render_template(parameters:, template:, template_path:)
|
|
110
|
+
case File.extname(template_path)
|
|
111
|
+
when '.erb'
|
|
112
|
+
RenderErb.new(template_name: template_path).call(template, **parameters)
|
|
113
|
+
else
|
|
114
|
+
template
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def report_file_contents(contents)
|
|
119
|
+
say "\n", verbose: true
|
|
120
|
+
say(
|
|
121
|
+
contents
|
|
122
|
+
.each_line
|
|
123
|
+
.map { |line| line == "\n" ? "\n" : " #{line}" }.join,
|
|
124
|
+
verbose: true
|
|
125
|
+
)
|
|
126
|
+
say "\n", verbose: true
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def write_file(contents:, file_path:)
|
|
130
|
+
step { check_if_file_is_directory(file_path:) }
|
|
131
|
+
step { check_if_file_already_exists(file_path:) }
|
|
132
|
+
|
|
133
|
+
file_system.write_file(file_path, contents) unless dry_run?
|
|
134
|
+
rescue Cuprum::Cli::Dependencies::FileSystem::DirectoryNotFoundError
|
|
135
|
+
error =
|
|
136
|
+
file_not_writeable_error(file_path:, reason: 'directory not found')
|
|
137
|
+
|
|
138
|
+
failure(error)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/cli/command'
|
|
4
|
+
require 'cuprum/cli/commands/file'
|
|
5
|
+
require 'cuprum/cli/commands/file/render_erb'
|
|
6
|
+
require 'cuprum/cli/commands/file/resolve_template'
|
|
7
|
+
|
|
8
|
+
module Cuprum::Cli::Commands::File
|
|
9
|
+
# Command for generating a templated file or files.
|
|
10
|
+
class NewCommand < Cuprum::Cli::Command
|
|
11
|
+
dependency :file_system
|
|
12
|
+
dependency :standard_io
|
|
13
|
+
|
|
14
|
+
include Cuprum::Cli::Options::Quiet
|
|
15
|
+
include Cuprum::Cli::Options::Verbose
|
|
16
|
+
|
|
17
|
+
argument :file_path, type: String, required: true
|
|
18
|
+
|
|
19
|
+
option :directories, type: :boolean, default: true
|
|
20
|
+
option :dry_run, type: :boolean, default: false
|
|
21
|
+
option :parent_class, type: String
|
|
22
|
+
option :templates,
|
|
23
|
+
type: Array,
|
|
24
|
+
default: Cuprum::Cli::Commands::File::Templates::DEFAULT_TEMPLATES
|
|
25
|
+
option :extra_flags,
|
|
26
|
+
type: :boolean,
|
|
27
|
+
variadic: true
|
|
28
|
+
|
|
29
|
+
description 'Generates a new templated file or files.'
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def excluded_tags
|
|
34
|
+
excluded = []
|
|
35
|
+
|
|
36
|
+
extra_flags.each do |flag, value|
|
|
37
|
+
excluded << flag if value == false
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
excluded
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def generate_file(file_path:, parameters:, template_path:) # rubocop:disable Metrics/MethodLength
|
|
44
|
+
file_path = resolve_file_path(file_path, **parameters)
|
|
45
|
+
command = GenerateFile.new(
|
|
46
|
+
file_system:,
|
|
47
|
+
standard_io:,
|
|
48
|
+
directories: directories?,
|
|
49
|
+
dry_run: dry_run?,
|
|
50
|
+
quiet: quiet?,
|
|
51
|
+
verbose: verbose?
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
parameters = parameters.merge(parent_class:)
|
|
55
|
+
|
|
56
|
+
step { command.call(file_path:, parameters:, template_path:) }
|
|
57
|
+
|
|
58
|
+
file_path
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def process
|
|
62
|
+
templates, parameters = step { resolve_template }
|
|
63
|
+
|
|
64
|
+
templates.map do |template|
|
|
65
|
+
file_path = template.fetch(:file_path, self.file_path)
|
|
66
|
+
template_path = template.fetch(:template)
|
|
67
|
+
|
|
68
|
+
step { generate_file(file_path:, parameters:, template_path:) }
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def resolve_file_path(file_path, **params)
|
|
73
|
+
params = tools.hash_tools.convert_keys_to_symbols(params)
|
|
74
|
+
|
|
75
|
+
format(file_path, params)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def resolve_template
|
|
79
|
+
command = Cuprum::Cli::Commands::File::ResolveTemplate.new(templates:)
|
|
80
|
+
|
|
81
|
+
command.call(file_path, except: excluded_tags)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def tools = @tools ||= SleepingKingStudios::Tools::Toolbelt.instance
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/command'
|
|
4
|
+
require 'herb'
|
|
5
|
+
|
|
6
|
+
require 'cuprum/cli/commands/file'
|
|
7
|
+
require 'cuprum/cli/errors/files/missing_parameter'
|
|
8
|
+
|
|
9
|
+
module Cuprum::Cli::Commands::File
|
|
10
|
+
# Utility command for generating file contents from an .erb template.
|
|
11
|
+
class RenderErb < Cuprum::Command
|
|
12
|
+
class RenderingContext < BasicObject; end
|
|
13
|
+
private_constant :RenderingContext
|
|
14
|
+
|
|
15
|
+
# @param template_name [String, nil] the name of the rendered template. Used
|
|
16
|
+
# for error reporting.
|
|
17
|
+
def initialize(template_name: nil)
|
|
18
|
+
super()
|
|
19
|
+
|
|
20
|
+
@template_name = template_name
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @return [String, nil] the name of the rendered template.
|
|
24
|
+
attr_reader :template_name
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def compilation_error(details)
|
|
29
|
+
message = 'unable to render ERB template'
|
|
30
|
+
message = "#{message} #{template_name}" if template_name
|
|
31
|
+
|
|
32
|
+
Cuprum::Cli::Errors::Files::TemplateError.new(message:, details:)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def empty_binding = RenderingContext.new.instance_exec { Kernel.binding }
|
|
36
|
+
|
|
37
|
+
def generate_binding(**params)
|
|
38
|
+
params.each.with_object(empty_binding) do |(key, value), binding|
|
|
39
|
+
binding.local_variable_set(key, value)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def generate_engine(template)
|
|
44
|
+
Herb::Engine.new(template)
|
|
45
|
+
rescue Herb::Engine::CompilationError,
|
|
46
|
+
Herb::Engine::SecurityError => exception
|
|
47
|
+
error = compilation_error(exception.message)
|
|
48
|
+
|
|
49
|
+
failure(error)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def missing_parameter_error(parameter_name)
|
|
53
|
+
Cuprum::Cli::Errors::Files::MissingParameter.new(
|
|
54
|
+
message: 'unable to render ERB template',
|
|
55
|
+
parameter_name:,
|
|
56
|
+
template_name:
|
|
57
|
+
)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def process(template, **params) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
61
|
+
engine = step { generate_engine(template) }
|
|
62
|
+
binding = generate_binding(**params)
|
|
63
|
+
|
|
64
|
+
binding.eval(engine.src)
|
|
65
|
+
rescue NameError => exception
|
|
66
|
+
error =
|
|
67
|
+
# @todo [RUBY_VERSION <= '3.3'] remove regexp case
|
|
68
|
+
if exception.message.match?(/RenderingContext:0x\h+>/)
|
|
69
|
+
# :nocov:
|
|
70
|
+
missing_parameter_error(exception.name)
|
|
71
|
+
# :nocov:
|
|
72
|
+
elsif exception.message.end_with?(RenderingContext.name) # rubocop:disable Lint/DuplicateBranch
|
|
73
|
+
missing_parameter_error(exception.name)
|
|
74
|
+
else
|
|
75
|
+
template_error(exception.message)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
failure(error)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def template_error(message)
|
|
82
|
+
Cuprum::Cli::Errors::Files::TemplateError.new(
|
|
83
|
+
message: "unable to render ERB template - #{message}",
|
|
84
|
+
template_name:
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/command'
|
|
4
|
+
|
|
5
|
+
require 'cuprum/cli/commands/file'
|
|
6
|
+
require 'cuprum/cli/errors/files/template_not_resolved'
|
|
7
|
+
|
|
8
|
+
module Cuprum::Cli::Commands::File
|
|
9
|
+
# Utility command for resolving a template and parameterized values.
|
|
10
|
+
class ResolveTemplate < Cuprum::Command
|
|
11
|
+
# @param templates [Array<Hash>] the defined templates.
|
|
12
|
+
def initialize(templates:)
|
|
13
|
+
super()
|
|
14
|
+
|
|
15
|
+
@templates = templates
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @return [Array<Hash>] the defined templates.
|
|
19
|
+
attr_reader :templates
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def default_params(file_path:, **params) # rubocop:disable Metrics/MethodLength
|
|
24
|
+
dir_name = File.dirname(file_path)
|
|
25
|
+
ext_name = File.extname(file_path)
|
|
26
|
+
base_name = File.basename(file_path)
|
|
27
|
+
short_name = base_name.split('.').first
|
|
28
|
+
|
|
29
|
+
{
|
|
30
|
+
base_name:,
|
|
31
|
+
dir_name:,
|
|
32
|
+
ext_name:,
|
|
33
|
+
file_path:,
|
|
34
|
+
short_name:,
|
|
35
|
+
**params
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def filter_templates(except:, file_templates:, only:)
|
|
40
|
+
file_templates = [file_templates] unless file_templates.is_a?(Array)
|
|
41
|
+
except = Array(except).map(&:to_s)
|
|
42
|
+
only = Array(only).map(&:to_s)
|
|
43
|
+
|
|
44
|
+
unless except.empty?
|
|
45
|
+
file_templates = reject_templates(file_templates, *except)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
unless only.empty?
|
|
49
|
+
file_templates = select_templates(file_templates, *only)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
file_templates
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def match_pattern(pattern, file_path)
|
|
56
|
+
case pattern
|
|
57
|
+
when Proc
|
|
58
|
+
pattern.call(file_path)
|
|
59
|
+
when Regexp
|
|
60
|
+
match_regexp(pattern, file_path)
|
|
61
|
+
when String
|
|
62
|
+
{ file_path: } if file_path.end_with?(pattern)
|
|
63
|
+
else
|
|
64
|
+
# :nocov:
|
|
65
|
+
false
|
|
66
|
+
# :nocov:
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def match_regexp(pattern, file_path)
|
|
71
|
+
pattern
|
|
72
|
+
.match(file_path)
|
|
73
|
+
&.named_captures
|
|
74
|
+
&.then { |captures| tools.hash_tools.convert_keys_to_symbols(captures) }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def process(file_path, except: [], only: []) # rubocop:disable Metrics/MethodLength
|
|
78
|
+
templates.each do |hsh|
|
|
79
|
+
params = match_pattern(hsh.fetch(:pattern), file_path)
|
|
80
|
+
|
|
81
|
+
next unless params
|
|
82
|
+
|
|
83
|
+
file_templates = hsh.fetch(:templates)
|
|
84
|
+
file_templates = step do
|
|
85
|
+
filter_templates(file_templates:, except:, only:)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
step { require_templates(file_path:, file_templates:, except:, only:) }
|
|
89
|
+
|
|
90
|
+
return success([file_templates, default_params(file_path:, **params)])
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
message = 'no template matching file path'
|
|
94
|
+
|
|
95
|
+
failure(template_not_resolved_error(file_path:, message:))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def reject_templates(file_templates, *filters)
|
|
99
|
+
file_templates.reject do |template|
|
|
100
|
+
types = template.fetch(:types, Array(template[:type])).map(&:to_s)
|
|
101
|
+
|
|
102
|
+
types.any? { |type| filters.include?(type) }
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def require_templates(file_path:, file_templates:, except:, only:)
|
|
107
|
+
return unless file_templates.empty?
|
|
108
|
+
|
|
109
|
+
options = {}
|
|
110
|
+
options[:except] = except unless except.empty?
|
|
111
|
+
options[:only] = only unless only.empty?
|
|
112
|
+
|
|
113
|
+
error = template_not_resolved_error(
|
|
114
|
+
file_path:,
|
|
115
|
+
message: 'all templates filtered out',
|
|
116
|
+
options:
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
failure(error)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def select_templates(file_templates, *filters)
|
|
123
|
+
file_templates.select do |template|
|
|
124
|
+
types = template.fetch(:types, Array(template[:type])).map(&:to_s)
|
|
125
|
+
|
|
126
|
+
types.any? { |type| filters.include?(type) }
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def template_not_resolved_error(**)
|
|
131
|
+
Cuprum::Cli::Errors::Files::TemplateNotResolved.new(**)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def tools = @tools ||= SleepingKingStudios::Tools::Toolbelt.instance
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
<% tools = SleepingKingStudios::Tools::Toolbelt.new %>
|
|
3
|
+
|
|
4
|
+
<% module_path = relative_path.sub(/\/\z/, '').split('/') %>
|
|
5
|
+
<% full_path = [*module_path, short_name.sub(/_spec\z/, '')] %>
|
|
6
|
+
require '<%= full_path.join('/') %>'
|
|
7
|
+
|
|
8
|
+
<%
|
|
9
|
+
qualified_module =
|
|
10
|
+
full_path.map { |rel| tools.str.camelize(rel) }.join('::')
|
|
11
|
+
%>
|
|
12
|
+
RSpec.describe <%= qualified_module %> do
|
|
13
|
+
pending
|
|
14
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
<% tools = SleepingKingStudios::Tools::Toolbelt.new %>
|
|
3
|
+
|
|
4
|
+
<% if relative_path.empty? %>
|
|
5
|
+
<% if defined?(parent_class) && parent_class %>
|
|
6
|
+
class <%= tools.str.camelize(short_name) %> < <%= parent_class %>
|
|
7
|
+
|
|
8
|
+
end
|
|
9
|
+
<% else %>
|
|
10
|
+
module <%= tools.str.camelize(short_name) %>
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
<% end %>
|
|
14
|
+
<% else %>
|
|
15
|
+
<% module_path = relative_path.sub(/\/\z/, '').split('/') %>
|
|
16
|
+
require '<%= module_path.join('/') %>'
|
|
17
|
+
|
|
18
|
+
module <%= module_path.map { |rel| tools.str.camelize(rel) }.join('::') %>
|
|
19
|
+
<% if defined?(parent_class) && parent_class %>
|
|
20
|
+
class <%= tools.str.camelize(short_name) %> < <%= parent_class %>
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
<% else %>
|
|
24
|
+
module <%= tools.str.camelize(short_name) %>
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
<% end %>
|
|
28
|
+
end
|
|
29
|
+
<% end %>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/cli/commands/file'
|
|
4
|
+
|
|
5
|
+
module Cuprum::Cli::Commands::File
|
|
6
|
+
# Namespace for defining templates for generated files.
|
|
7
|
+
module Templates
|
|
8
|
+
RSPEC_PATTERN = <<~PATTERN.strip.then { |pattern| /#{pattern}/xo }
|
|
9
|
+
\\A
|
|
10
|
+
(?<root_path>\\w+#{File::SEPARATOR})?
|
|
11
|
+
(?<relative_path>(\\w+#{File::SEPARATOR})*)
|
|
12
|
+
(?<base_name>\\w+)_spec\\.rb
|
|
13
|
+
\\z
|
|
14
|
+
PATTERN
|
|
15
|
+
private_constant :RSPEC_PATTERN
|
|
16
|
+
|
|
17
|
+
RUBY_PATTERN = <<~PATTERN.strip.then { |pattern| /#{pattern}/xo }
|
|
18
|
+
\\A
|
|
19
|
+
(?<root_path>\\w+#{File::SEPARATOR})?
|
|
20
|
+
(?<relative_path>(\\w+#{File::SEPARATOR})*)
|
|
21
|
+
(?<base_name>\\w+)\\.rb
|
|
22
|
+
\\z
|
|
23
|
+
PATTERN
|
|
24
|
+
private_constant :RUBY_PATTERN
|
|
25
|
+
|
|
26
|
+
TEMPLATES_PATH =
|
|
27
|
+
File
|
|
28
|
+
.join(
|
|
29
|
+
Cuprum::Cli.gem_path,
|
|
30
|
+
'lib',
|
|
31
|
+
'cuprum',
|
|
32
|
+
'cli',
|
|
33
|
+
'commands',
|
|
34
|
+
'file',
|
|
35
|
+
'templates'
|
|
36
|
+
)
|
|
37
|
+
.freeze
|
|
38
|
+
private_constant :TEMPLATES_PATH
|
|
39
|
+
|
|
40
|
+
# Default templates used to generate Ruby and RSpec files.
|
|
41
|
+
DEFAULT_TEMPLATES = [
|
|
42
|
+
{
|
|
43
|
+
name: 'RSpec File',
|
|
44
|
+
pattern: RSPEC_PATTERN,
|
|
45
|
+
templates: {
|
|
46
|
+
file_path: '%<root_path>s%<relative_path>s%<base_name>s_spec.rb',
|
|
47
|
+
template: File.join(TEMPLATES_PATH, 'rspec.rb.erb'),
|
|
48
|
+
types: %i[ruby rspec spec test]
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'Ruby File (With Spec)',
|
|
53
|
+
pattern: RUBY_PATTERN,
|
|
54
|
+
templates: [
|
|
55
|
+
{
|
|
56
|
+
file_path: '%<root_path>s%<relative_path>s%<base_name>s.rb',
|
|
57
|
+
template: File.join(TEMPLATES_PATH, 'ruby.rb.erb'),
|
|
58
|
+
type: :ruby
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
file_path: 'spec/%<relative_path>s%<base_name>s_spec.rb',
|
|
62
|
+
template: File.join(TEMPLATES_PATH, 'rspec.rb.erb'),
|
|
63
|
+
types: %i[ruby rspec spec test]
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
].then do |ary|
|
|
68
|
+
SleepingKingStudios::Tools::Toolbelt.instance.array_tools.deep_freeze(ary)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/cli/commands'
|
|
4
|
+
|
|
5
|
+
module Cuprum::Cli::Commands
|
|
6
|
+
# Namespace for commands that create or manage files.
|
|
7
|
+
module File
|
|
8
|
+
autoload :GenerateFile, 'cuprum/cli/commands/file/generate_file'
|
|
9
|
+
autoload :NewCommand, 'cuprum/cli/commands/file/new_command'
|
|
10
|
+
autoload :RenderErb, 'cuprum/cli/commands/file/render_erb'
|
|
11
|
+
autoload :ResolveTemplate, 'cuprum/cli/commands/file/resolve_template'
|
|
12
|
+
autoload :Templates, 'cuprum/cli/commands/file/templates'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cuprum/cli'
|
|
4
|
+
|
|
5
|
+
module Cuprum::Cli
|
|
6
|
+
# Namespace for predefined commands.
|
|
7
|
+
module Commands
|
|
8
|
+
autoload :Ci, 'cuprum/cli/commands/ci'
|
|
9
|
+
autoload :File, 'cuprum/cli/commands/file'
|
|
10
|
+
autoload :EchoCommand, 'cuprum/cli/commands/echo_command'
|
|
11
|
+
end
|
|
12
|
+
end
|