glebm/i18n-tasks

View on GitHub
lib/i18n/tasks/command/options/data.rb

Summary

Maintainability
A
35 mins
Test Coverage
B
84%
# frozen_string_literal: true

require 'i18n/tasks/command/option_parsers/enum'

module I18n::Tasks
  module Command
    module Options
      module Data
        include Command::DSL

        DATA_FORMATS = %w[yaml json keys].freeze
        OUT_FORMATS  = ['terminal-table', *DATA_FORMATS, 'inspect', 'key-values'].freeze

        format_arg = proc do |type, values|
          default = values.first
          arg type,
              '-f',
              '--format FORMAT',
              values,
              { 'yml' => 'yaml' },
              t("i18n_tasks.cmd.args.desc.#{type}", valid_text: values * ', ', default_text: default),
              parser: OptionParsers::Enum::Parser.new(values,
                                                      proc do |value, valid|
                                                        I18n.t('i18n_tasks.cmd.errors.invalid_format',
                                                               invalid: value, valid: valid * ', ')
                                                      end)
        end

        # i18n-tasks-use t('i18n_tasks.cmd.args.desc.data_format')
        format_arg.call(:data_format, DATA_FORMATS)

        # i18n-tasks-use t('i18n_tasks.cmd.args.desc.out_format')
        format_arg.call(:out_format, OUT_FORMATS)

        # @return [I18n::Tasks::Data::Tree::Siblings]
        def forest_pos_or_stdin!(opt, format = opt[:format])
          parse_forest(pos_or_stdin!(opt), format)
        end

        # @return [Array<I18n::Tasks::Data::Tree::Siblings>] trees read from stdin and positional arguments
        def forests_stdin_and_pos!(opt, num = false, format = opt[:format])
          args = opt[:arguments] || []
          if opt[:nostdin]
            sources = []
          else
            sources = [$stdin.read]
            num -= 1 if num
          end
          if num
            num.times { sources << args.shift }
          else
            sources += args
            args.clear
          end
          sources.map { |src| parse_forest(src, format) }
        end

        def merge_forests_stdin_and_pos!(opt)
          forests_stdin_and_pos!(opt).inject(i18n.empty_forest) do |result, forest|
            result.merge! forest
          end
        end

        # @return [I18n::Tasks::Data::Tree::Siblings]
        def parse_forest(src, format)
          fail CommandError, I18n.t('i18n_tasks.cmd.errors.pass_forest') unless src

          if format == 'keys'
            ::I18n::Tasks::Data::Tree::Siblings.from_key_names parse_keys(src)
          else
            ::I18n::Tasks::Data::Tree::Siblings.from_nested_hash i18n.data.adapter_parse(src, format)
          end
        end

        def parse_keys(src)
          Array(src).compact.flat_map { |v| v.strip.split(/\s*[,\s\n]\s*/) }.map(&:presence).compact
        end

        def print_forest(forest, opts, version = :show_tree)
          format = opts[:format].to_s
          case format
          when 'terminal-table'
            terminal_report.send(version, forest)
          when 'inspect'
            puts forest.inspect
          when 'keys'
            puts forest.key_names(root: true)
          when 'key-values'
            puts(forest.key_values(root: true).map { |kv| kv.join("\t") })
          when *DATA_FORMATS
            puts i18n.data.adapter_dump forest.to_hash(true), format
          end
        end
      end
    end
  end
end