Ruby cli: Difference between revisions

From wikinotes
(Created page with " = Param Parsing, Raw = <blockquote> <syntaxhighlight lang="ruby"> #!/usr/bin/env ruby EXECUTABLE = File.basename(__FILE__) ARGV.count.times do |index| case ARGV[index] when '-h', '--help' help_msg <<~HELP #{EXECUTABLE} [-h] DESCRIPTION: does things PARAMS: $1: foo HELP puts(help_msg) exit(0) else puts "error" exit(1) end end </syntaxhighlight> </blockquote><!-- Param Parsing -->")
 
 
(16 intermediate revisions by the same user not shown)
Line 1: Line 1:
Some rough starting points for creating commandline interfaces in ruby.<br>
salt to taste.


= Param Parsing, Raw =
= Param Parsing, Raw =
<blockquote>
<blockquote>
{{ expand
| no structure
|
<syntaxhighlight lang="ruby">
<syntaxhighlight lang="ruby">
#!/usr/bin/env ruby
#!/usr/bin/env ruby
Line 7: Line 12:
EXECUTABLE = File.basename(__FILE__)
EXECUTABLE = File.basename(__FILE__)


name = "unknown"
age = "unknown"
shift = 0
ARGV.count.times do |index|
ARGV.count.times do |index|
  if shift > 0
    shift -= 1
    next
  end
   case ARGV[index]
   case ARGV[index]
   when '-h', '--help'
   when '-h', '--help'
     help_msg <<~HELP
     helpmsg = <<~HELP
      #{EXECUTABLE} [-h]
    #{EXECUTABLE} [-h] [-n NAME] [-a AGE]
 
    DESCRIPTION:
      says hello
 
    PARAMS:
      -n --name:
        assign a name
 
      -a --age:
        assign an age


      DESCRIPTION:
    EXAMPLE:
        does things
      #{EXECUTABLE} -n my-name -a 30


      PARAMS:
        $1:  foo
     HELP
     HELP
     puts(help_msg)
     puts(helpmsg)
     exit(0)
     exit(0)
  when '-n', '--name'
    name = ARGV[index+1]
    shift += 1
  when '-a', '--age'
    age = ARGV[index+1]
    shift += 1
   else
   else
     puts "error"
     puts "error"
     exit(1)
     exit(1)
   end
   end
end
end
puts("hello, #{name} with age #{age}")
</syntaxhighlight>
</syntaxhighlight>
}}
{{ expand
| enumerator structure
|
<syntaxhighlight lang="ruby">
#!/usr/bin/env ruby
EXECUTABLE = File.basename(__FILE__)
class ArgumentIterator
  def initialize(argv)
    @argv = argv
    @index = 0
  end
  def shift(n = 1)
    n.times.map { next_item }
  end
  def next_item
    val = @argv[@index]
    @index += 1
    val
  end
  def each
    Enumerator.new do |enum|
      loop do
        break if @index >= @argv.count
        enum.yield([self, next_item])
      end
    end.each { |this, val| yield(this, val) }
  end
end
class CommandlineInterface
  Args = Struct.new(:name, :age)
  def help_msg
    <<~HELP
    #{EXECUTABLE} [-h] [-n NAME] [-a AGE]
    DESCRIPTION:
      says hello
    PARAMS:
      -n --name:
        assign a name
      -a --age:
        assign an age
    EXAMPLE:
      #{EXECUTABLE} -n my-name -a 30
    HELP
  end
  def parse_args(argv)
    name = "unknown"
    age = "unknown"
    ArgumentIterator.new(argv).each do |iterator, arg|
      case arg
      when '-h', '--help'
        puts(help_msg)
        exit(0)
      when '-n', '--name'
        name, = iterator.shift
      when '-a', '--age'
        age, = iterator.shift
      else
        $stderr.puts("[ERROR] unexpected argument #{arg}")
        exit(1)
      end
    end
    Args.new(name, age)
  end
end
cli = CommandlineInterface.new
args = cli.parse_args(ARGV)
puts("hello, #{args.name} with age #{args.age}")
</syntaxhighlight>
}}
</blockquote><!-- Param Parsing -->
</blockquote><!-- Param Parsing -->
= Optparse =
<blockquote>
Ruby ships also ships with [[ruby optparse]].<br>
It works by defining a DSL for params (ex. <code>opts.on("-n NAME", "--name NAME"</code>), and defining callbacks for each param.<br>
I think it's a bit more complicated than it needs to be.
Example from the docs:
<syntaxhighlight lang="ruby">
require 'optparse'
options = {}
OptionParser.new do |parser|
  parser.on("-r", "--require LIBRARY",
            "Require the LIBRARY before executing your script") do |lib|
    puts "You required #{lib}!"
  end
end.parse!
</syntaxhighlight>
</blockquote><!-- Optparse -->

Latest revision as of 16:44, 29 October 2022

Some rough starting points for creating commandline interfaces in ruby.
salt to taste.

Param Parsing, Raw

no structure

#!/usr/bin/env ruby

EXECUTABLE = File.basename(__FILE__)

name = "unknown"
age = "unknown"
shift = 0
ARGV.count.times do |index|
  if shift > 0
    shift -= 1
    next
  end

  case ARGV[index]
  when '-h', '--help'
    helpmsg = <<~HELP
    #{EXECUTABLE} [-h] [-n NAME] [-a AGE]

    DESCRIPTION:
      says hello

    PARAMS:
      -n --name:
        assign a name

      -a --age:
        assign an age

    EXAMPLE:
      #{EXECUTABLE} -n my-name -a 30

    HELP
    puts(helpmsg)
    exit(0)

  when '-n', '--name'
    name = ARGV[index+1]
    shift += 1

  when '-a', '--age'
    age = ARGV[index+1]
    shift += 1

  else
    puts "error"
    exit(1)

  end

end

puts("hello, #{name} with age #{age}")

enumerator structure


#!/usr/bin/env ruby

EXECUTABLE = File.basename(__FILE__)


class ArgumentIterator
  def initialize(argv)
    @argv = argv
    @index = 0
  end

  def shift(n = 1)
    n.times.map { next_item }
  end

  def next_item
    val = @argv[@index]
    @index += 1
    val
  end

  def each
    Enumerator.new do |enum|
      loop do
        break if @index >= @argv.count

        enum.yield([self, next_item])
      end
    end.each { |this, val| yield(this, val) }
  end
end


class CommandlineInterface
  Args = Struct.new(:name, :age)

  def help_msg
    <<~HELP
    #{EXECUTABLE} [-h] [-n NAME] [-a AGE]

    DESCRIPTION:
      says hello

    PARAMS:
      -n --name:
        assign a name

      -a --age:
        assign an age

    EXAMPLE:
      #{EXECUTABLE} -n my-name -a 30

    HELP
  end

  def parse_args(argv)
    name = "unknown"
    age = "unknown"

    ArgumentIterator.new(argv).each do |iterator, arg|
      case arg
      when '-h', '--help'
        puts(help_msg)
        exit(0)

      when '-n', '--name'
        name, = iterator.shift

      when '-a', '--age'
        age, = iterator.shift

      else
        $stderr.puts("[ERROR] unexpected argument #{arg}")
        exit(1)

      end
    end

    Args.new(name, age)
  end
end


cli = CommandlineInterface.new
args = cli.parse_args(ARGV)
puts("hello, #{args.name} with age #{args.age}")

Optparse

Ruby ships also ships with ruby optparse.
It works by defining a DSL for params (ex. opts.on("-n NAME", "--name NAME"), and defining callbacks for each param.
I think it's a bit more complicated than it needs to be.

Example from the docs:

require 'optparse'

options = {}
OptionParser.new do |parser|
  parser.on("-r", "--require LIBRARY",
            "Require the LIBRARY before executing your script") do |lib|
    puts "You required #{lib}!"
  end
end.parse!