Class: Aspera::Cli::CommandLine

Inherits:
Object
  • Object
show all
Defined in:
lib/aspera/cli/command_line.rb

Overview

Command line split in tokens, in original order. Tokens are never removed, only marked as consumed, so that positions are kept.

An option without inline value claims the next token as its value (--opt val, -O val), unless that token looks like an option. If the option turns out to be a flag, the claimed token is given back to positional arguments.

Instance Method Summary collapse

Constructor Details

#initialize(argv) ⇒ CommandLine

Returns a new instance of CommandLine.

Parameters:

  • argv (Array<String>) —

    command line arguments



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
# File 'lib/aspera/cli/command_line.rb', line 112

def initialize(argv)
  # @type [Array<Option, Argument>]
  @tokens = []
  # Option token being applied (used by `@:` extended value)
  @current_option = nil
  # When set, only positional arguments after this token are available
  @arguments_after = nil
  process_options = true
  argv.each do |value|
    if process_options && value.eql?(Option::STOP)
      process_options = false
    elsif process_options && Option.option?(value)
      @tokens.push(Option.parse(value))
    else
      argument = Argument.new(value)
      previous = @tokens.last
      if process_options && previous.is_a?(Option) && !previous.inline? && previous.value_token.nil?
        previous.value_token = argument
        argument.owner = previous
      end
      @tokens.push(argument)
    end
  end
  Log.log.trace1 { "arguments=#{pending_arguments},options=#{pending_options}" }
end

Instance Method Details

#abbreviated_option_tokens ⇒ Array<Option>

Returns option tokens whose name was resolved as an abbreviation.

Returns:

  • (Array<Option>) —

    option tokens whose name was resolved as an abbreviation



139
140
141
# File 'lib/aspera/cli/command_line.rb', line 139

def abbreviated_option_tokens
  @tokens.select { |t| t.is_a?(Option) && !t.abbreviation_of.nil? }
end

#consume(tok, takes_value:) ⇒ String?

Mark option token as applied, and get its value.

Parameters:

  • tok (Option) —

    option token

  • takes_value (Boolean) —

    false for flags: claimed token is given back to positional arguments

Returns:

  • (String, nil) —

    value, or nil for flags

Raises:

  • (BadArgument) —

    if option takes a value and none was given



153
154
155
156
157
158
159
160
# File 'lib/aspera/cli/command_line.rb', line 153

def consume(tok, takes_value:)
  tok.consumed = true
  return release(tok) unless takes_value
  return tok.inline_value if tok.inline?
  Aspera.assert(!tok.value_token.nil?, type: BadArgument) { "Option #{tok.raw} requires a value" }
  tok.value_token.consumed = true
  tok.value_token.value
end

#each_long_option_with_value {|tok| ... } ⇒ Object

Consume all long options with a value, whether applied or not.

Yield Parameters:

  • tok (Option) —

    long option token with a value



220
221
222
223
224
225
226
227
# File 'lib/aspera/cli/command_line.rb', line 220

def each_long_option_with_value
  @tokens.each do |tok|
    next unless tok.is_a?(Option) && tok.short_char.nil? && !tok.value.nil?
    yield(tok)
    tok.consumed = true
    tok.value_token&.consumed = true
  end
end

#pending_arguments ⇒ Array<String>

Returns values of available positional arguments.

Returns:

  • (Array<String>) —

    values of available positional arguments



180
181
182
# File 'lib/aspera/cli/command_line.rb', line 180

def pending_arguments
  positional_tokens.map(&:value)
end

#pending_option_tokens ⇒ Array<Option>

Returns option tokens not applied yet.

Returns:

  • (Array<Option>) —

    option tokens not applied yet



144
145
146
# File 'lib/aspera/cli/command_line.rb', line 144

def pending_option_tokens
  @tokens.select { |t| t.is_a?(Option) && !t.consumed }
end

#pending_options ⇒ Array<String>

Returns options not applied yet, with their value if separate.

Returns:

  • (Array<String>) —

    options not applied yet, with their value if separate



185
186
187
# File 'lib/aspera/cli/command_line.rb', line 185

def pending_options
  pending_option_tokens.map(&:to_s)
end

#shift_arguments(multiple) ⇒ Array<String>

Consume positional arguments.

Parameters:

  • multiple (false, true, String) —

    consumption mode: false — consume exactly one token true — consume all remaining tokens String — consume up to the marker token (marker is consumed too, not returned), or all if absent

Returns:

  • (Array<String>) —

    consumed values



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/aspera/cli/command_line.rb', line 195

def shift_arguments(multiple)
  arg_tokens = positional_tokens
  selected =
    case multiple
    when false then arg_tokens.first(1)
    when true then arg_tokens
    when String
      index = arg_tokens.index { |t| t.value.eql?(multiple) }
      arg_tokens[index].consumed = true unless index.nil?
      arg_tokens.take(index || arg_tokens.length)
    else Aspera.error_unexpected_value(multiple) { 'multiple' }
    end
  selected.each { |t| t.consumed = true }
  selected.map(&:value)
end

#unshift_argument(value) ⇒ Object

Add an argument before the available positional arguments

Parameters:

  • value (String) —

    argument value



213
214
215
216
# File 'lib/aspera/cli/command_line.rb', line 213

def unshift_argument(value)
  index = @tokens.index { |t| t.is_a?(Argument) && t.positional? } || @tokens.length
  @tokens.insert(index, Argument.new(value))
end

#with_arguments_after_current_option ⇒ Object

Execute block with only positional arguments after current option available, if any



172
173
174
175
176
177
# File 'lib/aspera/cli/command_line.rb', line 172

def with_arguments_after_current_option
  @arguments_after = @current_option
  yield
ensure
  @arguments_after = nil
end

#with_current_option(tok) ⇒ Object

Execute block with tok as current option

Parameters:

  • tok (Option) —

    option token being applied



164
165
166
167
168
169
# File 'lib/aspera/cli/command_line.rb', line 164

def with_current_option(tok)
  @current_option = tok
  yield
ensure
  @current_option = nil
end