1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
# frozen_string_literal: true
module Unparser
# Unparser CLI implementation
class CLI
EXIT_SUCCESS = 0
EXIT_FAILURE = 1
class Target
include AbstractType
# Path target
class Path < self
include Concord.new(:path)
# Validation for this target
#
# @return [Validation]
def validation
Validation.from_path(path)
end
# Literal for this target
#
# @return [Validation]
def literal_validation
Validation::Literal.from_path(path)
end
end
# String target
class String
include Concord.new(:string)
# Validation for this target
#
# @return [Validation]
def validation
Validation.from_string(string)
end
# Literal for this target
#
# @return [Validation]
def literal_validation
Validation::Literal.from_string(path)
end
end # String
end # Target
private_constant(*constants(false))
# Run CLI
#
# @param [Array<String>] arguments
#
# @return [Integer]
# the exit status
#
# @api private
#
def self.run(*arguments)
new(*arguments).exit_status
end
# Initialize object
#
# @param [Array<String>] arguments
#
# @return [undefined]
#
# @api private
def initialize(arguments)
@ignore = Set.new
@targets = []
@fail_fast = false
@start_with = nil
@success = true
@validation = :validation
@verbose = false
opts = OptionParser.new do |builder|
add_options(builder)
end
opts.parse!(arguments).each do |name|
@targets.concat(targets(name))
end
end
# Add options
#
# @param [OptionParser] builder
#
# @return [undefined]
#
# @api private
#
# rubocop:disable Metrics/MethodLength
def add_options(builder)
builder.banner = 'usage: unparse [options] FILE [FILE]'
builder.separator('')
builder.on('-e', '--evaluate SOURCE') do |source|
@targets << Target::String.new(source)
end
builder.on('--start-with FILE') do |path|
@start_with = targets(path).first
end
builder.on('-v', '--verbose') do
@verbose = true
end
builder.on('-l', '--literal') do
@validation = :literal_validation
end
builder.on('--ignore FILE') do |file|
@ignore.merge(targets(file))
end
builder.on('--fail-fast') do
@fail_fast = true
end
end
# rubocop:enable Metrics/MethodLength
# Return exit status
#
# @return [Integer]
#
# @api private
#
def exit_status
effective_targets.each do |target|
process_target(target)
break if @fail_fast && !@success
end
@success ? EXIT_SUCCESS : EXIT_FAILURE
end
private
def process_target(target)
validation = target.public_send(@validation)
if validation.success?
puts validation.report if @verbose
puts "Success: #{validation.identification}"
else
puts validation.report
puts "Error: #{validation.identification}"
@success = false
end
end
def effective_targets
if @start_with
reject = true
@targets.reject do |targets|
if reject && targets.eql?(@start_with)
reject = false
end
reject
end
else
@targets
end.reject(&@ignore.method(:include?))
end
def targets(file_name)
if File.directory?(file_name)
Dir.glob(File.join(file_name, '**/*.rb'))
elsif File.file?(file_name)
[file_name]
else
Dir.glob(file_name)
end.map { |file| Target::Path.new(Pathname.new(file)) }
end
end # CLI
end # Unparser
|