optparsegen 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c224a84b9f8bc19e937d687806e1171f2b8d9c00
4
+ data.tar.gz: aed0a9eda0f3e95194a4f0e4320dee8d263fe4eb
5
+ SHA512:
6
+ metadata.gz: 58d646498865d522f5eb80e81c52005cd77cb26469e153b4acebfb690ff4a4f0d3af6ff6a50f6b6c78313ff720794791c67dccd8c5e04172ffb6c0459d09c5b0
7
+ data.tar.gz: fdc547b174c848784af0c117d4310142c48ef8991b375295273a927c519857b2020377b84f2e9f571ff40286df5064d5cf8ef8e7edc7cf0bb1b8bfea00e0dc24
data/bin/optparsegen ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'optparsegen'
4
+
5
+ options = Struct.new(:format).new(:scopt)
6
+
7
+ OptionParser.new do |opts|
8
+ opts.banner = %Q(Usage: #{File.basename($0)} [options] <file>
9
+
10
+ optparsegen converts program usage text into equivalent ruby 'optparse'
11
+ code. It reads the text from the filename passed as the only argument
12
+ on the command line or from standard input.
13
+
14
+ Options:
15
+ )
16
+
17
+ opts.on('-f', '--format', '=[FORMAT]', [:scopt], 'Input usage text format. Default: scopt') do |v|
18
+ options.format = v
19
+ end
20
+
21
+ opts.on_tail('-h', '--help', 'Show this message.') do
22
+ puts opts
23
+ exit
24
+ end
25
+ end.parse!
26
+
27
+ OptParseGen.generate(ARGF.read, options.format)
@@ -0,0 +1,109 @@
1
+ class OptParseGen::ScoptParser
2
+ def initialize(input)
3
+ @tape = input
4
+ @options = []
5
+ @current = OptParseGen::Option.new
6
+ end
7
+
8
+ def parse
9
+ state = :parse_any
10
+
11
+ while state != nil
12
+ lchomp_until!(is_not_space)
13
+ state = send(state)
14
+ end
15
+
16
+ @options
17
+ end
18
+
19
+ private
20
+ def is_not_space
21
+ /[^\s]/
22
+ end
23
+
24
+ def is_space
25
+ /\s/
26
+ end
27
+
28
+ def lchomp_until!(matches)
29
+ p = @tape.index(matches)
30
+ if p == nil
31
+ @tape.slice!(-1)
32
+ else
33
+ @tape.slice!(0, p)
34
+ end
35
+ end
36
+
37
+ def parse_any
38
+ case
39
+ when @tape.start_with?('-') then
40
+ @tape.slice!(0, 1)
41
+ :parse_opt
42
+ when (p = @tape.index("\n")) != nil then
43
+ @tape.slice!(0, p)
44
+ :parse_any
45
+ else
46
+ nil
47
+ end
48
+ end
49
+
50
+ def parse_opt
51
+ if @tape[0] == '-'
52
+ @tape.slice!(0)
53
+ :parse_opt_name
54
+ else
55
+ :parse_opt_short
56
+ end
57
+ end
58
+
59
+ def parse_opt_short
60
+ short = lchomp_until!(is_space).chop!
61
+ if short
62
+ @current.short = short
63
+ :parse_any
64
+ else
65
+ raise 'expected short option name'
66
+ end
67
+ end
68
+
69
+ def parse_opt_name
70
+ name = lchomp_until!(is_space)
71
+ if name
72
+ @current.name = name
73
+ :parse_opt_value_or_desc
74
+ else
75
+ raise 'expected option name'
76
+ end
77
+ end
78
+
79
+ def parse_opt_value_or_desc
80
+ if @tape.start_with?('<')
81
+ :parse_opt_value
82
+ else
83
+ :parse_opt_desc
84
+ end
85
+ end
86
+
87
+ def parse_opt_value
88
+ value = lchomp_until!(is_space)
89
+ if value
90
+ # TODO: Handle value examples.
91
+ # @current.value = value
92
+ :parse_opt_desc
93
+ else
94
+ raise 'expected value'
95
+ end
96
+ end
97
+
98
+ def parse_opt_desc
99
+ desc = lchomp_until!("\n")
100
+ if desc
101
+ @current.description = desc
102
+ @options.push(@current)
103
+ @current = OptParseGen::Option.new
104
+ :parse_any
105
+ else
106
+ raise 'expected description'
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,13 @@
1
+ # The main entry point for OptParseGen.
2
+ class OptParseGen
3
+ # Represents a single option.
4
+ Option = Struct.new(:name, :short, :description)
5
+
6
+ # Generates 'optparse' code from the given input and format.
7
+ def self.generate(input, format)
8
+ require "optparsegen/#{format}"
9
+ parser = OptParseGen.const_get("#{format.capitalize}Parser").new(input)
10
+ options = parser.parse
11
+ puts options
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ require 'minitest/autorun'
2
+ require 'optparsegen'
3
+ require 'optparsegen/scopt'
4
+
5
+ class ScoptParserTest < Minitest::Test
6
+ def test_basic_parse
7
+ input = 'Usage: myprogram [options]
8
+
9
+ --help Shows this usage text.
10
+ -d, --work-date <value> Generate data for this date. Default: 2017-01-02
11
+ -i, --input-dir <value> Load input data from this directory. Default: hdfs:///path/to/input
12
+ -o, --output-dir <value>
13
+ Output generated data to this directory. Default: hdfs:///path/to/output
14
+ -x, --extra-jars <jar1>,<jar2>...
15
+ Extra jars to include.
16
+ '
17
+
18
+ options = parse(input)
19
+
20
+ assert_equal(5, options.size)
21
+ assert_equal('extra-jars help input-dir output-dir work-date', options.map { |o| o.name }.sort.join(' '))
22
+ assert_equal('Extra jars to include.', options.find { |o| o.name == 'extra-jars' }.description)
23
+ end
24
+
25
+ def test_parse_error
26
+ input = 'Usage: myprogram [options]
27
+
28
+ --help
29
+ '
30
+ err = assert_raises RuntimeError do
31
+ parse(input)
32
+ end
33
+ assert_equal('expected description', err.message)
34
+ end
35
+
36
+ private
37
+ def parse(input)
38
+ OptParseGen::ScoptParser.new(input).parse
39
+ end
40
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: optparsegen
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tyler Sommer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-04 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ executables:
16
+ - optparsegen
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/optparsegen
21
+ - lib/optparsegen.rb
22
+ - lib/optparsegen/scopt.rb
23
+ - test/test_scopt.rb
24
+ homepage:
25
+ licenses:
26
+ - MIT
27
+ metadata: {}
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 2.4.5.1
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: Generate ruby optparse code from usage text.
48
+ test_files:
49
+ - test/test_scopt.rb