3

I have a trouble with passing an arguments to my ruby file. IE,

OptionParser.new do |opts|
  opts.banner = 'Usage: mp3split.rb [options]'

  opts.on('-f', '--filename fName1,fName2,fName3', Array, 'absolute or relative pathes to file') { |f| options[:filenames] = f }
end.parse!

This approach requires me to write this commands:

ruby mp3split.rb --filename fursov_13.mp3,fursov_14.mp3,fursov_14_2.mp3,fursov_15.mp3,fursov_16.mp3,fursov_17.mp3

But I want to get array by this:

ruby mp3split.rb --filename fursov_13.mp3 fursov_14.mp3 fursov_14_2.mp3 fursov_15.mp3 fursov_16.mp3 fursov_17.mp3

How can I implement this functionality? I can't find anything helpful about this in docs.

Alex Antonov
  • 14,134
  • 7
  • 65
  • 142

2 Answers2

3

With OptionParser you can’t. There is a workaround, though, when there is the only list you need to handle that way and you won’t pass other arguments to the script. OptionParser splits the input by spaces before it processes it. The unkeyed arguments remain in ARGV global constant after parsing. Assuming everything described above is met, here we go:

OptionParser.new do |opts|
  options[:filenames] = []
  opts.banner = 'Usage: mp3split.rb [options]'        
  opts.on('-f', '--filename fName1 fName2 fName3', Array, 
          'absolute or relative pathes to file') do |f|
    options[:filenames] |= [*f]
  end
end.parse!

options[:filenames] |= ARGV

I apparently fixed another glitch within your code: options[:filenames] should be appended not overwritten on every occurence of -f switch, OptionParser supports script -f f1 -f f2 -f f3.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • Maybe you mean `options[:filenames] ||= ARGV` instead of `options[:filenames] |= ARGV` ? I can't find `|=` method in the ruby api – Alex Antonov Apr 29 '15 at 10:50
  • `a |= b` is a ruby-wide shorthand for `a = a | b`. On arrays it is a [union](http://ruby-doc.org/core-2.2.1/Array.html#method-i-7C). – Aleksei Matiushkin Apr 29 '15 at 11:12
  • Thanks, but I want exactly what I want. Is there any other ruby libraries? – Alex Antonov May 02 '15 at 11:11
  • How do you expect this parser to handle `-f a.txt -g` where -g is perfectly valid existing file name? – Aleksei Matiushkin May 02 '15 at 14:25
  • I needn't `-g` flag in my parser :) – Alex Antonov May 04 '15 at 09:40
  • You were asking whether there is an option parser, that makes what you want. Since `-f a.txt -f` is ambiguous for any parser that permits arbitrary amount of options separated by the same symbol as option markers themselves (space in your case,) your claim is ambiguous. You might parse `ARGV` as I suggested, or force commas as file list delimiter, or even write your own Turing-incomplete parser for such a specific case. – Aleksei Matiushkin May 04 '15 at 09:51
0

I was shocked to learn that OptionParter can't do such a simple thing, so I switched to Thor, for example:

require 'thor'

class EmqxCLI < Thor
  desc 'add_user USER_ID PASSWORD [IS_SUPERUSER]', 'Add a user (optional: set true/false for is_superuser)'
  def add_user(user_id, password, is_superuser = false)
    emqx = EmqxApi.new
    emqx.add_user(user_id, password, is_superuser)
  end

  desc 'remove_user USER_ID', 'Remove a user'
  def remove_user(user_id)
    emqx = EmqxApi.new
    emqx.remove_user(user_id)
  end

  desc 'list_users', 'List users'
  def list_users
    emqx = EmqxApi.new
    emqx.list_users
  end
end

EmqxCLI.start(ARGV)

Which I can now run with:

$ ruby emqx.rb add_user user1 pass1

It also generates a lovely output when running without arguments:

# ruby emqx.rb
Commands:
  emqx.rb add_user USER_ID PASSWORD [IS_SUPERUSER]  # Add a user (optional: set true/false for is_superuser)
  emqx.rb help [COMMAND]                            # Describe available commands or one specific command
  emqx.rb list_users                                # List users
  emqx.rb remove_user USER_ID                       # Remove a user
Roman Gaufman
  • 1,104
  • 1
  • 13
  • 17