lib/monolens/command.rb in monolens-0.5.3 vs lib/monolens/command.rb in monolens-0.6.0

- old
+ new

@@ -9,45 +9,55 @@ @argv = argv @stdin = stdin @stdout = stdout @stderr = stderr @pretty = false + @enclose = [] + @output_format = :json + @stream = false + @fail_strategy = 'fail' + @override = false + # + @input_file = nil + @use_stdin = false end attr_reader :argv, :stdin, :stdout, :stderr - attr_reader :pretty + attr_reader :pretty, :stream, :override + attr_reader :enclose_map, :fail_strategy + attr_reader :input_file, :use_stdin def self.call(argv, stdin = $stdin, stdout = $stdout, stderr = $stderr) new(argv, stdin, stdout, stderr).call end def call - lens, input = options.parse!(argv) - show_help_and_exit if lens.nil? || input.nil? + lens, @input_file = options.parse!(argv) + show_help_and_exit if lens.nil? || (@input_file.nil? && !use_stdin) - lens, input = read_file(lens), read_file(input) + lens_data, input = read_file(lens), read_input + lens = build_lens(lens_data) error_handler = ErrorHandler.new - lens = Monolens.lens(lens) result = lens.call(input, error_handler: error_handler) unless error_handler.empty? stderr.puts(error_handler.report) end - if result - output = if pretty - JSON.pretty_generate(result) - else - result.to_json - end - - stdout.puts output - end + output_result(result) if result rescue Monolens::LensError => ex stderr.puts("[#{ex.location.join('/')}] #{ex.message}") do_exit(-2) end + def read_input + if use_stdin + JSON.parse(stdin.read) + else + read_file(@input_file) + end + end + def read_file(file) case ::File.extname(file) when /json$/ content = ::File.read(file) JSON.parse(content) @@ -85,12 +95,99 @@ opts.on('--version', 'Show version and exit') do stdout.puts "Monolens v#{VERSION} - (c) Enspirit #{Date.today.year}" do_exit(0) end + opts.on('-m', '--map', 'Enclose the loaded lens inside an array.map') do + @enclose << :map + end + opts.on('-l', '--literal', 'Enclose the loaded lens inside core.literal') do + @enclose << :literal + end + opts.on('--on-error=STRATEGY', 'Apply a specific strategy on error') do |strategy| + @fail_strategy = strategy + end + opts.on('-ILIB', 'Add a folder to ruby load path') do |lib| + $LOAD_PATH.unshift(lib) + end + opts.on('-rLIB', 'Add a ruby require of a lib') do |lib| + require(lib) + end + opts.on( '--stdin', 'Takes input data from STDIN') do + @use_stdin = true + end opts.on('-p', '--[no-]pretty', 'Show version and exit') do |pretty| @pretty = pretty end + opts.on('-y', '--yaml', 'Print output in YAML') do + @output_format = :yaml + end + opts.on('-s', '--stream', 'Stream mode: output each result item separately') do + @stream = true + end + opts.on('-j', '--json', 'Print output in JSON') do + @output_format = :json + end + opts.on('--override', 'Write output back to the input file') do + @override = true + end end + end + + def build_lens(lens_data) + lens_data = @enclose.inject(lens_data) do |memo, lens_name| + case lens_name + when :map + { + 'array.map' => { + 'on_error' => ['handler', fail_strategy].compact, + 'lenses' => memo, + } + } + when :literal + { + 'core.literal' => { + 'defn' => memo, + } + } + end + end + Monolens.lens(lens_data) + end + + def output_result(result) + with_output_io do |io| + output = case @output_format + when :json + output_json(result, io) + when :yaml + output_yaml(result, io) + end + end + end + + def with_output_io(&block) + if override + ::File.open(@input_file, 'w', &block) + else + block.call(stdout) + end + end + + def output_json(result, io) + method = pretty ? :pretty_generate : :generate + if stream + fail!("Stream mode only works with an output Array") unless result.is_a?(::Enumerable) + result.each do |item| + io.puts JSON.send(method, item) + end + else + io.puts JSON.send(method, result) + end + end + + def output_yaml(result, io) + output = stream ? YAML.dump_stream(*result) : YAML.dump(result) + io.puts output end end end