Module: SOPT

Defined in:
lib/rbbt/util/simpleopt.rb,
lib/rbbt/util/simpleopt/doc.rb,
lib/rbbt/util/simpleopt/get.rb,
lib/rbbt/util/simpleopt/parse.rb,
lib/rbbt/util/simpleopt/setup.rb,
lib/rbbt/util/simpleopt/accessor.rb

Constant Summary collapse

GOT_OPTIONS =
IndiferentHash.setup({})

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.commandObject

Returns the value of attribute command.



4
5
6
# File 'lib/rbbt/util/simpleopt/doc.rb', line 4

def command
  @command
end

.descriptionObject

Returns the value of attribute description.



4
5
6
# File 'lib/rbbt/util/simpleopt/doc.rb', line 4

def description
  @description
end

.input_defaultsObject

Returns the value of attribute input_defaults.



4
5
6
# File 'lib/rbbt/util/simpleopt/accessor.rb', line 4

def input_defaults
  @input_defaults
end

.input_descriptionsObject

Returns the value of attribute input_descriptions.



4
5
6
# File 'lib/rbbt/util/simpleopt/accessor.rb', line 4

def input_descriptions
  @input_descriptions
end

.input_shortcutsObject

Returns the value of attribute input_shortcuts.



4
5
6
# File 'lib/rbbt/util/simpleopt/accessor.rb', line 4

def input_shortcuts
  @input_shortcuts
end

.input_typesObject

Returns the value of attribute input_types.



4
5
6
# File 'lib/rbbt/util/simpleopt/accessor.rb', line 4

def input_types
  @input_types
end

.inputsObject

Returns the value of attribute inputs.



4
5
6
# File 'lib/rbbt/util/simpleopt/accessor.rb', line 4

def inputs
  @inputs
end

.summaryObject

Returns the value of attribute summary.



4
5
6
# File 'lib/rbbt/util/simpleopt/doc.rb', line 4

def summary
  @summary
end

.synopsysObject

Returns the value of attribute synopsys.



4
5
6
# File 'lib/rbbt/util/simpleopt/doc.rb', line 4

def synopsys
  @synopsys
end

Class Method Details

.allObject



7
8
9
# File 'lib/rbbt/util/simpleopt/accessor.rb', line 7

def self.all
  @all ||= {}
end

.consume(args = ARGV) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/rbbt/util/simpleopt/get.rb', line 3

def self.consume(args = ARGV)
  i = 0
  values = {}
  while i < args.length do
    current = args[i]
    break if current == "--"
    if m = current.match(/--?(.+?)(?:=(.+))?$/)
      key = $1
      value = $2

      input = inputs.include?(key)? key : shortcuts[key]

      if input.nil?
        i += 1
        next
      else
        args.delete_at i
      end
    else
      i += 1
      next
    end

    if input_types[input] == :string
      value = args.delete_at(i) if value.nil?
      values[input] = value
    else
      if value.nil? and %w(F false FALSE no).include?(args[i])
        Log.warn "Boolean values are best specified as #{current}=[true|false], not #{ current } [true|false]. Token '#{args[i]}' following '#{current}' automatically assigned as value" 
        value = args.delete_at(i)
      end
      values[input] = %w(F false FALSE no).include?(value)? false : true
    end
  end

  IndiferentHash.setup values
  GOT_OPTIONS.merge! values

  values
end

.delete_inputs(inputs) ⇒ Object



40
41
42
43
44
45
46
47
48
49
# File 'lib/rbbt/util/simpleopt/accessor.rb', line 40

def self.delete_inputs(inputs)
  inputs.each do |input|
    input = input.to_s
    self.shortcuts.delete self.input_shortcuts.delete(input)
    self.inputs.delete input
    self.input_types.delete input
    self.input_defaults.delete input
    self.input_descriptions.delete input
  end
end

.docObject



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/rbbt/util/simpleopt/doc.rb', line 80

def self.doc
  doc = <<-EOF
#{Log.color :magenta}#{command}(1) -- #{summary}
#{"=" * (command.length + summary.length + 7)}#{Log.color :reset}

#{ Log.color :magenta, "## SYNOPSYS"}

#{Log.color :blue, synopsys}

#{ Log.color :magenta, "## DESCRIPTION"}

#{Misc.format_paragraph description}

#{ Log.color :magenta, "## OPTIONS"}

#{input_doc(inputs, input_types, input_descriptions, input_defaults, input_shortcuts)}
  EOF
end

.fix_shortcut(short, long) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/rbbt/util/simpleopt/parse.rb', line 4

def self.fix_shortcut(short, long)
  return short unless short and shortcuts.include?(short)

  current = shortcuts.select{|s,l| l == long}.collect{|s,l| s }.first
  return current if current

  chars = long.chars.to_a
  current = [chars.shift]
  short = current * ""

  if (shortcuts.include?(short) and not shortcuts[short] == long) 
    if long.index "-" or long.index "_"
      parts = long.split(/[_-]/)
      acc = parts.collect{|s| s[0] } * ""
      return acc unless shortcuts.include? acc
    elsif m = long.match(/(\d+)/)
      n = m[0]
      acc = long[0] + n
      return acc unless shortcuts.include? acc
    end
  end

  while shortcuts.include?(short) && shortcuts[short] != long 
    next_letter = chars.shift
    next_letter = chars.shift while %w(. - _).include?(next_letter)
    return nil if next_letter.nil?
    current << next_letter
    short = current * ""
  end

  return nil if shortcuts.include? short

  short
end

.get(opt_str) ⇒ Object



44
45
46
47
# File 'lib/rbbt/util/simpleopt/get.rb', line 44

def self.get(opt_str)
  SOPT.parse(opt_str)
  SOPT.consume(ARGV)
end

.input_doc(inputs, input_types = nil, input_descriptions = nil, input_defaults = nil, input_shortcuts = nil) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/rbbt/util/simpleopt/doc.rb', line 48

def self.input_doc(inputs, input_types = nil, input_descriptions = nil, input_defaults = nil, input_shortcuts = nil)
  type = description = default = nil
  shortcut = ""
  seen = []
  inputs.collect do |name|
    next if seen.include? name
    seen << name

    type = input_types[name] unless input_types.nil?
    description = input_descriptions[name] unless input_descriptions.nil?
    default = input_defaults[name] unless input_defaults.nil?

    name = name.to_s

    case input_shortcuts
    when nil, FalseClass
      shortcut = nil
    when Hash
      shortcut = input_shortcuts[name] 
    when TrueClass
      shortcut = fix_shortcut(name[0], name)
    end

    type = :string if type.nil?
    register(shortcut, name, type, description) unless self.inputs.include? name

    name  = SOPT.input_format(name, type.to_sym, default, shortcut) 
    description 
    Misc.format_definition_list_item(name, description, 80, 31, nil)
  end * "\n"
end

.input_format(name, type = nil, default = nil, short = nil) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/rbbt/util/simpleopt/doc.rb', line 28

def self.input_format(name, type = nil, default = nil, short = nil)
  input_str = (short.nil? or short.empty?) ? "--#{name}" : "-#{short},--#{name}"
  input_str = Log.color(:blue, input_str)
  extra = case type
  when nil
    ""
  when :boolean
    "[=false]" 
  when :tsv, :text
    "=<file|->"
  when :array
    "=<list|file|->"
  else
    "=<#{ type }>"
  end
  #extra << " (default: #{Array === default ? (default.length > 3 ? default[0..2]*", " + ', ...' : default*", " ): default})" if default != nil
  extra << " (default: #{Misc.fingerprint(default)})" if default != nil
  input_str << Log.color(:green, extra)
end

.parse(opt_str) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/rbbt/util/simpleopt/parse.rb', line 48

def self.parse(opt_str)
  info = {}

  inputs = []
  if opt_str.include? "\n"
    re = /\n+/
  else
    re = /:/
  end
  opt_str.split(re).each do |entry|
    entry.strip!
    next if entry.empty?
    names, _sep, description = entry.partition /\s+/
    short, long, asterisk = names.match(/\s*(?:-(.+))?(?:--(.+?))([*])?$/).values_at 1,2,3 

    inputs << long
    register short, long, asterisk, description
  end
  inputs
end

.register(short, long, asterisk, description) ⇒ Object



39
40
41
42
43
44
45
46
# File 'lib/rbbt/util/simpleopt/parse.rb', line 39

def self.register(short, long, asterisk, description)
  short = fix_shortcut(short, long)
  shortcuts[short] = long if short
  inputs << long
  input_shortcuts[long] = short
  input_descriptions[long] = description
  input_types[long] = asterisk ? :string : :boolean
end

.require(options, *parameters) ⇒ Object



49
50
51
52
53
# File 'lib/rbbt/util/simpleopt/get.rb', line 49

def self.require(options, *parameters)
  parameters.flatten.each do |parameter|
    raise ParameterException, "Parameter '#{ Log.color :blue, parameter }' not given" if options[parameter].nil?
  end
end

.resetObject



35
36
37
38
# File 'lib/rbbt/util/simpleopt/accessor.rb', line 35

def self.reset
  @shortcuts = {}
  @all = {}
end

.setup(str) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/rbbt/util/simpleopt/setup.rb', line 6

def self.setup(str)
  parts = str.split(/\n\n+/)

  summary = parts.shift unless parts.first =~ /^\s*\$-/
  synopsys = parts.shift if parts.first =~ /^\s*\$/

  description = []
  while parts.first and parts.first !~ /^\s*-/
    description << parts.shift
  end
  description = description * "\n\n"

  options = parts.collect{|part| part.split("\n").select{|l| l=~ /^\s*-/ }  }.flatten.compact * "\n"

  synopsys.sub!(/^\$\s+/,'') if synopsys

  SOPT.summary = summary.strip if summary
  SOPT.synopsys = synopsys.strip if synopsys
  SOPT.description = description.strip if description
  SOPT.parse options  if options

  SOPT.consume
end

.shortcutsObject



11
12
13
# File 'lib/rbbt/util/simpleopt/accessor.rb', line 11

def self.shortcuts
  @shortcuts ||= {}
end

.usageObject



51
52
53
54
# File 'lib/rbbt/util/simpleopt/accessor.rb', line 51

def self.usage
  puts SOPT.doc
  exit 0
end