class EasyOptions::Parser

Constants

BashOutput

Attributes

arguments[RW]
documentation[RW]
options[RW]

Public Class Methods

check_bash_output() click to toggle source
# File easyoptions.rb, line 238
def self.check_bash_output
    $0 = ENV['from'] || $PROGRAM_NAME
    $PROGRAM_NAME == ENV['from']
end
finish(error) click to toggle source
# File easyoptions.rb, line 231
def self.finish(error)
    warn "Error: #{error}."
    warn 'See --help for usage and options.'
    puts 'exit 1' if BashOutput
    exit false
end
new() click to toggle source
# File easyoptions.rb, line 109
def initialize
    @known_options = [Option.new(:help, :h)]
    @documentation = parse_doc
    @arguments = []
    @options = {}
end

Public Instance Methods

parse() click to toggle source
# File easyoptions.rb, line 133
def parse
    # Parse known options from documentation
    @documentation.map do |line|
        line = line.strip
        case line
        when /^-h, --help.*/ then next
        when /^--help, -h.*/ then next
        when /^-.*, --.*/    then line = line.split(/(^-|,\s--|\s)/);  @known_options << Option.new(line[4], line[2])
        when /^--.*, -.*/    then line = line.split(/(--|,\s-|\s)/);   @known_options << Option.new(line[2], line[4])
        when /^--.*=.*/      then line = line.split(/(--|=|\s)/);      @known_options << Option.new(line[2], nil, false)
        when /^--.* .*/      then line = line.split(/(--|\s)/);        @known_options << Option.new(line[2], nil)
        end
    end

    # Format arguments input
    raw_arguments = ARGV.map do |argument|
        if argument =~ /^-[^-].*$/i
            argument.split('')[1..-1].map { |char| "-#{char}" }
        else
            argument
        end
    end.flatten

    # Parse the provided options
    raw_arguments.each_with_index do |argument, index|
        unknown_option = true
        @known_options.each do |known_option|

            # Boolean option
            if known_option.in?(argument) && known_option.boolean
                @options[known_option.long] = true
                unknown_option = false
                break

            # Option with value in next parameter
            elsif known_option.in?(argument) && !known_option.boolean
                value = raw_arguments[index + 1]
                Parser.finish("you must specify a value for #{known_option}") if !value || value.start_with?('-')
                value = value.to_i if value =~ /^[0-9]+$/
                @options[known_option.long] = value
                unknown_option = false
                break

            # Option with value after equal sign
            elsif known_option.in_with_value?(argument) && !known_option.boolean
                value = argument.split('=')[1]
                value = value.to_i if value =~ /^[0-9]+$/
                @options[known_option.long] = value
                unknown_option = false
                break

            # Long option with unnecessary value
            elsif known_option.in_with_value?(argument) && known_option.boolean
                value = argument.split('=')[1]
                Parser.finish("#{known_option} does not accept a value (you specified \"#{value}\")")
            end
        end

        # Unrecognized option
        Parser.finish("unrecognized option \"#{argument}\"") if unknown_option && argument.start_with?('-')
    end

    # Help option
    if @options[:help]
        if BashOutput
            print "printf '"
            puts @documentation
            puts "'"
            puts 'exit'
        else
            puts @documentation
        end
        exit(-1)
    end

    # Regular arguments
    next_is_value = false
    raw_arguments.each do |argument|
        if argument.start_with?('-')
            known_option = @known_options.find { |option| option.in?(argument) }
            next_is_value = (known_option && !known_option.boolean)
        else
            arguments << argument unless next_is_value
            next_is_value = false
        end
    end

    # Bash support
    return unless BashOutput
    @options.keys.each do |name|
        puts "#{name}=\"#{@options[name].to_s.sub('true', 'yes')}\""
    end
    puts 'unset arguments'
    arguments.each do |argument|
        puts "arguments+=(\"#{argument}\")"
    end
end
parse_doc() click to toggle source
# File easyoptions.rb, line 116
def parse_doc
    begin
        doc = File.readlines($PROGRAM_NAME)
    rescue Errno::ENOENT
        exit false
    end
    doc = doc.find_all do |line|
        line =~ /^##[^#]*/
    end
    doc.map do |line|
        line.strip!
        line.sub!(/^## ?/, '')
        line.gsub!(/@script.name/, File.basename($PROGRAM_NAME))
        line.gsub(/@#/, '@')
    end
end