class TTY::Option::Parser::Environments

Constants

ENV_VAR_RE

Public Class Methods

new(environments, check_invalid_params: true, raise_on_parse_error: false) click to toggle source

Create a command line env variables parser

@param [Array<Environment>] environments

the list of environment variables

@param [Hash] config

the configuration settings

@api public

# File lib/tty/option/parser/environments.rb, line 25
def initialize(environments, check_invalid_params: true,
               raise_on_parse_error: false)
  @environments = environments
  @check_invalid_params = check_invalid_params
  @error_aggregator =
    ErrorAggregator.new(raise_on_parse_error: raise_on_parse_error)
  @required_check = RequiredCheck.new(@error_aggregator)
  @arity_check = ArityCheck.new(@error_aggregator)
  @pipeline = Pipeline.new(@error_aggregator)
  @parsed = {}
  @remaining = []
  @names = {}
  @arities = Hash.new(0)

  @environments.each do |env_arg|
    @names[env_arg.name] = env_arg
    @arity_check << env_arg if env_arg.multiple?

    if env_arg.default?
      case env_arg.default
      when Proc
        assign_envvar(env_arg, env_arg.default.())
      else
        assign_envvar(env_arg, env_arg.default)
      end
    elsif env_arg.required?
      @required_check << env_arg
    end
  end
end

Public Instance Methods

parse(argv, env) { |env_var, value| ... } click to toggle source

Read environment variable(s) from command line or ENV hash

@param [Array<String>] argv @param [Hash<String,Object>] env

@api public

# File lib/tty/option/parser/environments.rb, line 62
def parse(argv, env)
  @argv = argv.dup
  @env = env

  loop do
    env_var, value = next_envvar
    if !env_var.nil?
      @required_check.delete(env_var)
      @arities[env_var.key] += 1

      if block_given?
        yield(env_var, value)
      end
      assign_envvar(env_var, value)
    end
    break if @argv.empty?
  end

  @environments.each do |env_arg|
    if (value = env[env_arg.name])
      @required_check.delete(env_arg)
      @arities[env_arg.key] += 1
      assign_envvar(env_arg, value)
    end
  end

  @arity_check.(@arities)
  @required_check.()

  [@parsed, @remaining, @error_aggregator.errors]
end

Private Instance Methods

assign_envvar(env_arg, val) click to toggle source

@api private

# File lib/tty/option/parser/environments.rb, line 145
def assign_envvar(env_arg, val)
  value = @pipeline.(env_arg, val)

  if env_arg.multiple?
    allowed = env_arg.arity < 0 || @arities[env_arg.key] <= env_arg.arity
    if allowed
      case value
      when Hash
        (@parsed[env_arg.key] ||= {}).merge!(value)
      else
        Array(value).each do |v|
          (@parsed[env_arg.key] ||= []) << v
        end
      end
    else
      @remaining << "#{env_arg.name}=#{value}"
    end
  else
    @parsed[env_arg.key] = value
  end
end
consume_arguments(values: []) click to toggle source

Consume multi argument

@api private

# File lib/tty/option/parser/environments.rb, line 132
def consume_arguments(values: [])
  while (value = @argv.first) &&
    !option?(value) && !keyword?(value) && !env_var?(value)

    val = @argv.shift
    parts = val.include?("&") ? val.split(/&/) : [val]
    parts.each { |part| values << part }
  end

  values
end
next_envvar() click to toggle source
# File lib/tty/option/parser/environments.rb, line 96
def next_envvar
  env_var, value = nil, nil

  while !@argv.empty? && !env_var?(@argv.first)
    @remaining << @argv.shift
  end

  if @argv.empty?
    return
  else
    environment = @argv.shift
  end

  if (match = environment.match(ENV_VAR_RE))
    _, name, val = *match.to_a

    if (env_var = @names[name])
      if env_var.multi_argument? &&
          !(consumed = consume_arguments).empty?
        value = [val] + consumed
      else
        value = val
      end
    elsif @check_invalid_params
      @error_aggregator.(InvalidParameter.new("invalid environment #{match}"))
    else
      @remaining << match.to_s
    end
  end

  [env_var, value]
end