nanoc3 3.0.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.
Files changed (116) hide show
  1. data/ChangeLog +3 -0
  2. data/LICENSE +19 -0
  3. data/NEWS.rdoc +262 -0
  4. data/README.rdoc +80 -0
  5. data/Rakefile +11 -0
  6. data/bin/nanoc3 +16 -0
  7. data/lib/nanoc3/base/code_snippet.rb +42 -0
  8. data/lib/nanoc3/base/compiler.rb +225 -0
  9. data/lib/nanoc3/base/compiler_dsl.rb +110 -0
  10. data/lib/nanoc3/base/core_ext/array.rb +21 -0
  11. data/lib/nanoc3/base/core_ext/hash.rb +23 -0
  12. data/lib/nanoc3/base/core_ext/string.rb +14 -0
  13. data/lib/nanoc3/base/core_ext.rb +5 -0
  14. data/lib/nanoc3/base/data_source.rb +197 -0
  15. data/lib/nanoc3/base/dependency_tracker.rb +291 -0
  16. data/lib/nanoc3/base/errors.rb +95 -0
  17. data/lib/nanoc3/base/filter.rb +60 -0
  18. data/lib/nanoc3/base/item.rb +87 -0
  19. data/lib/nanoc3/base/item_rep.rb +236 -0
  20. data/lib/nanoc3/base/layout.rb +53 -0
  21. data/lib/nanoc3/base/notification_center.rb +68 -0
  22. data/lib/nanoc3/base/plugin.rb +88 -0
  23. data/lib/nanoc3/base/preprocessor_context.rb +37 -0
  24. data/lib/nanoc3/base/rule.rb +37 -0
  25. data/lib/nanoc3/base/rule_context.rb +68 -0
  26. data/lib/nanoc3/base/site.rb +334 -0
  27. data/lib/nanoc3/base.rb +25 -0
  28. data/lib/nanoc3/cli/base.rb +151 -0
  29. data/lib/nanoc3/cli/commands/autocompile.rb +89 -0
  30. data/lib/nanoc3/cli/commands/compile.rb +279 -0
  31. data/lib/nanoc3/cli/commands/create_item.rb +79 -0
  32. data/lib/nanoc3/cli/commands/create_layout.rb +94 -0
  33. data/lib/nanoc3/cli/commands/create_site.rb +320 -0
  34. data/lib/nanoc3/cli/commands/help.rb +71 -0
  35. data/lib/nanoc3/cli/commands/info.rb +114 -0
  36. data/lib/nanoc3/cli/commands/update.rb +96 -0
  37. data/lib/nanoc3/cli/commands.rb +13 -0
  38. data/lib/nanoc3/cli/logger.rb +73 -0
  39. data/lib/nanoc3/cli.rb +16 -0
  40. data/lib/nanoc3/data_sources/delicious.rb +66 -0
  41. data/lib/nanoc3/data_sources/filesystem.rb +231 -0
  42. data/lib/nanoc3/data_sources/filesystem_combined.rb +202 -0
  43. data/lib/nanoc3/data_sources/filesystem_common.rb +22 -0
  44. data/lib/nanoc3/data_sources/filesystem_compact.rb +232 -0
  45. data/lib/nanoc3/data_sources/last_fm.rb +103 -0
  46. data/lib/nanoc3/data_sources/twitter.rb +53 -0
  47. data/lib/nanoc3/data_sources.rb +20 -0
  48. data/lib/nanoc3/extra/auto_compiler.rb +97 -0
  49. data/lib/nanoc3/extra/chick.rb +119 -0
  50. data/lib/nanoc3/extra/context.rb +24 -0
  51. data/lib/nanoc3/extra/core_ext/time.rb +19 -0
  52. data/lib/nanoc3/extra/core_ext.rb +3 -0
  53. data/lib/nanoc3/extra/deployers/rsync.rb +64 -0
  54. data/lib/nanoc3/extra/deployers.rb +12 -0
  55. data/lib/nanoc3/extra/file_proxy.rb +31 -0
  56. data/lib/nanoc3/extra/validators/links.rb +0 -0
  57. data/lib/nanoc3/extra/validators/w3c.rb +71 -0
  58. data/lib/nanoc3/extra/validators.rb +12 -0
  59. data/lib/nanoc3/extra/vcs.rb +65 -0
  60. data/lib/nanoc3/extra/vcses/bazaar.rb +21 -0
  61. data/lib/nanoc3/extra/vcses/dummy.rb +20 -0
  62. data/lib/nanoc3/extra/vcses/git.rb +21 -0
  63. data/lib/nanoc3/extra/vcses/mercurial.rb +21 -0
  64. data/lib/nanoc3/extra/vcses/subversion.rb +21 -0
  65. data/lib/nanoc3/extra/vcses.rb +17 -0
  66. data/lib/nanoc3/extra.rb +16 -0
  67. data/lib/nanoc3/filters/bluecloth.rb +13 -0
  68. data/lib/nanoc3/filters/coderay.rb +17 -0
  69. data/lib/nanoc3/filters/erb.rb +19 -0
  70. data/lib/nanoc3/filters/erubis.rb +17 -0
  71. data/lib/nanoc3/filters/haml.rb +20 -0
  72. data/lib/nanoc3/filters/less.rb +13 -0
  73. data/lib/nanoc3/filters/markaby.rb +14 -0
  74. data/lib/nanoc3/filters/maruku.rb +14 -0
  75. data/lib/nanoc3/filters/rainpress.rb +13 -0
  76. data/lib/nanoc3/filters/rdiscount.rb +13 -0
  77. data/lib/nanoc3/filters/rdoc.rb +23 -0
  78. data/lib/nanoc3/filters/redcloth.rb +14 -0
  79. data/lib/nanoc3/filters/relativize_paths.rb +32 -0
  80. data/lib/nanoc3/filters/rubypants.rb +14 -0
  81. data/lib/nanoc3/filters/sass.rb +17 -0
  82. data/lib/nanoc3/filters.rb +37 -0
  83. data/lib/nanoc3/helpers/blogging.rb +226 -0
  84. data/lib/nanoc3/helpers/breadcrumbs.rb +25 -0
  85. data/lib/nanoc3/helpers/capturing.rb +71 -0
  86. data/lib/nanoc3/helpers/filtering.rb +46 -0
  87. data/lib/nanoc3/helpers/html_escape.rb +22 -0
  88. data/lib/nanoc3/helpers/link_to.rb +120 -0
  89. data/lib/nanoc3/helpers/rendering.rb +76 -0
  90. data/lib/nanoc3/helpers/tagging.rb +58 -0
  91. data/lib/nanoc3/helpers/text.rb +40 -0
  92. data/lib/nanoc3/helpers/xml_sitemap.rb +69 -0
  93. data/lib/nanoc3/helpers.rb +16 -0
  94. data/lib/nanoc3/package.rb +106 -0
  95. data/lib/nanoc3/tasks/clean.rake +16 -0
  96. data/lib/nanoc3/tasks/clean.rb +33 -0
  97. data/lib/nanoc3/tasks/deploy/rsync.rake +11 -0
  98. data/lib/nanoc3/tasks/validate.rake +35 -0
  99. data/lib/nanoc3/tasks.rb +9 -0
  100. data/lib/nanoc3.rb +19 -0
  101. data/vendor/cri/ChangeLog +0 -0
  102. data/vendor/cri/LICENSE +19 -0
  103. data/vendor/cri/NEWS +0 -0
  104. data/vendor/cri/README +4 -0
  105. data/vendor/cri/Rakefile +25 -0
  106. data/vendor/cri/lib/cri/base.rb +153 -0
  107. data/vendor/cri/lib/cri/command.rb +105 -0
  108. data/vendor/cri/lib/cri/core_ext/string.rb +41 -0
  109. data/vendor/cri/lib/cri/core_ext.rb +8 -0
  110. data/vendor/cri/lib/cri/option_parser.rb +186 -0
  111. data/vendor/cri/lib/cri.rb +12 -0
  112. data/vendor/cri/test/test_base.rb +6 -0
  113. data/vendor/cri/test/test_command.rb +6 -0
  114. data/vendor/cri/test/test_core_ext.rb +21 -0
  115. data/vendor/cri/test/test_option_parser.rb +279 -0
  116. metadata +225 -0
@@ -0,0 +1,41 @@
1
+ module Cri::CoreExtensions
2
+
3
+ module String
4
+
5
+ # Word-wraps and indents the string.
6
+ #
7
+ # +width+:: The maximal width of each line. This also includes indentation,
8
+ # i.e. the actual maximal width of the text is width-indentation.
9
+ #
10
+ # +indentation+:: The number of spaces to indent each wrapped line.
11
+ def wrap_and_indent(width, indentation)
12
+ # Split into paragraphs
13
+ paragraphs = self.split("\n").map { |p| p.strip }.reject { |p| p == '' }
14
+
15
+ # Wrap and indent each paragraph
16
+ paragraphs.map do |paragraph|
17
+ # Initialize
18
+ lines = []
19
+ line = ''
20
+
21
+ # Split into words
22
+ paragraph.split(/\s/).each do |word|
23
+ # Begin new line if it's too long
24
+ if (line + ' ' + word).length >= width
25
+ lines << line
26
+ line = ''
27
+ end
28
+
29
+ # Add word to line
30
+ line += (line == '' ? '' : ' ' ) + word
31
+ end
32
+ lines << line
33
+
34
+ # Join lines
35
+ lines.map { |l| ' '*indentation + l }.join("\n")
36
+ end.join("\n\n")
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,8 @@
1
+ module Cri::CoreExtensions
2
+ end
3
+
4
+ require 'cri/core_ext/string'
5
+
6
+ class String
7
+ include Cri::CoreExtensions::String
8
+ end
@@ -0,0 +1,186 @@
1
+ module Cri
2
+
3
+ # Cri::OptionParser is used for parsing commandline options.
4
+ class OptionParser
5
+
6
+ # Error that will be raised when an unknown option is encountered.
7
+ class IllegalOptionError < RuntimeError ; end
8
+
9
+ # Error that will be raised when an option without argument is
10
+ # encountered.
11
+ class OptionRequiresAnArgumentError < RuntimeError ; end
12
+
13
+ # Parses the commandline arguments in +arguments_and_options+, using the
14
+ # commandline option definitions in +definitions+.
15
+ #
16
+ # +arguments_and_options+ is an array of commandline arguments and
17
+ # options. This will usually be +ARGV+.
18
+ #
19
+ # +definitions+ contains a list of hashes defining which options are
20
+ # allowed and how they will be handled. Such a hash has three keys:
21
+ #
22
+ # :short:: The short name of the option, e.g. +a+. Do not include the '-'
23
+ # prefix.
24
+ #
25
+ # :long:: The long name of the option, e.g. +all+. Do not include the '--'
26
+ # prefix.
27
+ #
28
+ # :argument:: Whether this option's argument is required (:required),
29
+ # optional (:optional) or forbidden (:forbidden).
30
+ #
31
+ # A sample array of definition hashes could look like this:
32
+ #
33
+ # [
34
+ # { :short => 'a', :long => 'all', :argument => :forbidden },
35
+ # { :short => 'p', :long => 'port', :argument => :required },
36
+ # ]
37
+ #
38
+ # During parsing, two errors can be raised:
39
+ #
40
+ # IllegalOptionError:: An unrecognised option was encountered, i.e. an
41
+ # option that is not present in the list of option
42
+ # definitions.
43
+ #
44
+ # OptionRequiresAnArgumentError:: An option was found that did not have a
45
+ # value, even though this value was
46
+ # required.
47
+ #
48
+ # What will be returned, is a hash with two keys, :arguments and :options.
49
+ # The :arguments value contains a list of arguments, and the :options
50
+ # value contains a hash with key-value pairs for each option. Options
51
+ # without values will have a +nil+ value instead.
52
+ #
53
+ # For example, the following commandline options (which should not be
54
+ # passed as a string, but as an array of strings):
55
+ #
56
+ # foo -xyz -a hiss -s -m please --level 50 --father=ani -n luke squeak
57
+ #
58
+ # with the following option definitions:
59
+ #
60
+ # [
61
+ # { :short => 'x', :long => 'xxx', :argument => :forbidden },
62
+ # { :short => 'y', :long => 'yyy', :argument => :forbidden },
63
+ # { :short => 'z', :long => 'zzz', :argument => :forbidden },
64
+ # { :short => 'a', :long => 'all', :argument => :forbidden },
65
+ # { :short => 's', :long => 'stuff', :argument => :optional },
66
+ # { :short => 'm', :long => 'more', :argument => :optional },
67
+ # { :short => 'l', :long => 'level', :argument => :required },
68
+ # { :short => 'f', :long => 'father', :argument => :required },
69
+ # { :short => 'n', :long => 'name', :argument => :required }
70
+ # ]
71
+ #
72
+ # will be translated into:
73
+ #
74
+ # {
75
+ # :arguments => [ 'foo', 'hiss', 'squeak' ],
76
+ # :options => {
77
+ # :xxx => true,
78
+ # :yyy => true,
79
+ # :zzz => true,
80
+ # :all => true,
81
+ # :stuff => true,
82
+ # :more => 'please',
83
+ # :level => '50',
84
+ # :father => 'ani',
85
+ # :name => 'luke'
86
+ # }
87
+ # }
88
+ def self.parse(arguments_and_options, definitions)
89
+ # Don't touch original argument
90
+ unprocessed_arguments_and_options = arguments_and_options.dup
91
+
92
+ # Initialize
93
+ arguments = []
94
+ options = {}
95
+
96
+ # Determines whether we've passed the '--' marker or not
97
+ no_more_options = false
98
+
99
+ loop do
100
+ # Get next item
101
+ e = unprocessed_arguments_and_options.shift
102
+ break if e.nil?
103
+
104
+ # Handle end-of-options marker
105
+ if e == '--'
106
+ no_more_options = true
107
+ # Handle incomplete options
108
+ elsif e =~ /^--./ and !no_more_options
109
+ # Get option key, and option value if included
110
+ if e =~ /^--([^=]+)=(.+)$/
111
+ option_key = $1
112
+ option_value = $2
113
+ else
114
+ option_key = e[2..-1]
115
+ option_value = nil
116
+ end
117
+
118
+ # Find definition
119
+ definition = definitions.find { |d| d[:long] == option_key }
120
+ raise IllegalOptionError.new(option_key) if definition.nil?
121
+
122
+ if [ :required, :optional ].include?(definition[:argument])
123
+ # Get option value if necessary
124
+ if option_value.nil?
125
+ option_value = unprocessed_arguments_and_options.shift
126
+ if option_value.nil? || option_value =~ /^-/
127
+ if definition[:argument] == :required
128
+ raise OptionRequiresAnArgumentError.new(option_key)
129
+ else
130
+ unprocessed_arguments_and_options.unshift(option_value)
131
+ option_value = true
132
+ end
133
+ end
134
+ end
135
+
136
+ # Store option
137
+ options[definition[:long].to_sym] = option_value
138
+ else
139
+ # Store option
140
+ options[definition[:long].to_sym] = true
141
+ end
142
+ # Handle -xyz options
143
+ elsif e =~ /^-./ and !no_more_options
144
+ # Get option keys
145
+ option_keys = e[1..-1].scan(/./)
146
+
147
+ # For each key
148
+ option_keys.each do |option_key|
149
+ # Find definition
150
+ definition = definitions.find { |d| d[:short] == option_key }
151
+ raise IllegalOptionError.new(option_key) if definition.nil?
152
+
153
+ if option_keys.length > 1 and definition[:argument] == :required
154
+ # This is a combined option and it requires an argument, so complain
155
+ raise OptionRequiresAnArgumentError.new(option_key)
156
+ elsif [ :required, :optional ].include?(definition[:argument])
157
+ # Get option value
158
+ option_value = unprocessed_arguments_and_options.shift
159
+ if option_value.nil? || option_value =~ /^-/
160
+ if definition[:argument] == :required
161
+ raise OptionRequiresAnArgumentError.new(option_key)
162
+ else
163
+ unprocessed_arguments_and_options.unshift(option_value)
164
+ option_value = true
165
+ end
166
+ end
167
+
168
+ # Store option
169
+ options[definition[:long].to_sym] = option_value
170
+ else
171
+ # Store option
172
+ options[definition[:long].to_sym] = true
173
+ end
174
+ end
175
+ # Handle normal arguments
176
+ else
177
+ arguments << e
178
+ end
179
+ end
180
+
181
+ { :options => options, :arguments => arguments }
182
+ end
183
+
184
+ end
185
+
186
+ end
@@ -0,0 +1,12 @@
1
+ module Cri
2
+
3
+ # The current Cri version.
4
+ VERSION = '1.0'
5
+
6
+ end
7
+
8
+ # Load Cri
9
+ require 'cri/base'
10
+ require 'cri/command'
11
+ require 'cri/core_ext'
12
+ require 'cri/option_parser'
@@ -0,0 +1,6 @@
1
+ class Cri::BaseTest < MiniTest::Unit::TestCase
2
+
3
+ def test_stub
4
+ end
5
+
6
+ end
@@ -0,0 +1,6 @@
1
+ class Cri::CommandTest < MiniTest::Unit::TestCase
2
+
3
+ def test_stub
4
+ end
5
+
6
+ end
@@ -0,0 +1,21 @@
1
+ class Cri::CoreExtTest < MiniTest::Unit::TestCase
2
+
3
+ def test_string_wrap_and_indent
4
+ assert_equal(
5
+ "Lorem ipsum dolor sit amet, consectetur\n" +
6
+ "adipisicing elit, sed do eiusmod tempor\n" +
7
+ "incididunt ut labore et dolore magna\n" +
8
+ "aliqua.",
9
+ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.".wrap_and_indent(40, 0)
10
+ )
11
+
12
+ assert_equal(
13
+ " Lorem ipsum dolor sit amet,\n" +
14
+ " consectetur adipisicing elit, sed\n" +
15
+ " do eiusmod tempor incididunt ut\n" +
16
+ " labore et dolore magna aliqua.",
17
+ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.".wrap_and_indent(36, 4)
18
+ )
19
+ end
20
+
21
+ end
@@ -0,0 +1,279 @@
1
+ class Cri::OptionParserTest < MiniTest::Unit::TestCase
2
+
3
+ def test_parse_without_options
4
+ input = %w( foo bar baz )
5
+ definitions = []
6
+
7
+ result = Cri::OptionParser.parse(input, definitions)
8
+
9
+ assert_equal({}, result[:options])
10
+ assert_equal([ 'foo', 'bar', 'baz' ], result[:arguments])
11
+ end
12
+
13
+ def test_parse_with_invalid_option
14
+ input = %w( foo -x )
15
+ definitions = []
16
+
17
+ result = nil
18
+
19
+ assert_raises(Cri::OptionParser::IllegalOptionError) do
20
+ result = Cri::OptionParser.parse(input, definitions)
21
+ end
22
+ end
23
+
24
+ def test_parse_without_options
25
+ input = %w( foo )
26
+ definitions = [
27
+ { :long => 'aaa', :short => 'a', :argument => :forbidden }
28
+ ]
29
+
30
+ result = Cri::OptionParser.parse(input, definitions)
31
+
32
+ assert(!result[:options][:aaa])
33
+ end
34
+
35
+ def test_parse_with_long_valueless_option
36
+ input = %w( foo --aaa bar )
37
+ definitions = [
38
+ { :long => 'aaa', :short => 'a', :argument => :forbidden }
39
+ ]
40
+
41
+ result = Cri::OptionParser.parse(input, definitions)
42
+
43
+ assert(result[:options][:aaa])
44
+ assert_equal([ 'foo', 'bar' ], result[:arguments])
45
+ end
46
+
47
+ def test_parse_with_long_valueful_option
48
+ input = %w( foo --aaa xxx bar )
49
+ definitions = [
50
+ { :long => 'aaa', :short => 'a', :argument => :required }
51
+ ]
52
+
53
+ result = Cri::OptionParser.parse(input, definitions)
54
+
55
+ assert_equal({ :aaa => 'xxx' }, result[:options])
56
+ assert_equal([ 'foo', 'bar' ], result[:arguments])
57
+ end
58
+
59
+ def test_parse_with_long_valueful_equalsign_option
60
+ input = %w( foo --aaa=xxx bar )
61
+ definitions = [
62
+ { :long => 'aaa', :short => 'a', :argument => :required }
63
+ ]
64
+
65
+ result = Cri::OptionParser.parse(input, definitions)
66
+
67
+ assert_equal({ :aaa => 'xxx' }, result[:options])
68
+ assert_equal([ 'foo', 'bar' ], result[:arguments])
69
+ end
70
+
71
+ def test_parse_with_long_valueful_option_with_missing_value
72
+ input = %w( foo --aaa )
73
+ definitions = [
74
+ { :long => 'aaa', :short => 'a', :argument => :required }
75
+ ]
76
+
77
+ result = nil
78
+
79
+ assert_raises(Cri::OptionParser::OptionRequiresAnArgumentError) do
80
+ result = Cri::OptionParser.parse(input, definitions)
81
+ end
82
+ end
83
+
84
+ def test_parse_with_two_long_valueful_options
85
+ input = %w( foo --all --port 2 )
86
+ definitions = [
87
+ { :long => 'all', :short => 'a', :argument => :required },
88
+ { :long => 'port', :short => 'p', :argument => :required }
89
+ ]
90
+
91
+ result = nil
92
+
93
+ assert_raises(Cri::OptionParser::OptionRequiresAnArgumentError) do
94
+ result = Cri::OptionParser.parse(input, definitions)
95
+ end
96
+ end
97
+
98
+ def test_parse_with_long_valueless_option_with_optional_value
99
+ input = %w( foo --aaa )
100
+ definitions = [
101
+ { :long => 'aaa', :short => 'a', :argument => :optional }
102
+ ]
103
+
104
+ result = Cri::OptionParser.parse(input, definitions)
105
+
106
+ assert(result[:options][:aaa])
107
+ assert_equal([ 'foo' ], result[:arguments])
108
+ end
109
+
110
+ def test_parse_with_long_valueful_option_with_optional_value
111
+ input = %w( foo --aaa xxx )
112
+ definitions = [
113
+ { :long => 'aaa', :short => 'a', :argument => :optional }
114
+ ]
115
+
116
+ result = Cri::OptionParser.parse(input, definitions)
117
+
118
+ assert_equal({ :aaa => 'xxx' }, result[:options])
119
+ assert_equal([ 'foo' ], result[:arguments])
120
+ end
121
+
122
+ def test_parse_with_long_valueless_option_with_optional_value_and_more_options
123
+ input = %w( foo --aaa -b -c )
124
+ definitions = [
125
+ { :long => 'aaa', :short => 'a', :argument => :optional },
126
+ { :long => 'bbb', :short => 'b', :argument => :forbidden },
127
+ { :long => 'ccc', :short => 'c', :argument => :forbidden }
128
+ ]
129
+
130
+ result = Cri::OptionParser.parse(input, definitions)
131
+
132
+ assert(result[:options][:aaa])
133
+ assert(result[:options][:bbb])
134
+ assert(result[:options][:ccc])
135
+ assert_equal([ 'foo' ], result[:arguments])
136
+ end
137
+
138
+ def test_parse_with_short_valueless_options
139
+ input = %w( foo -a bar )
140
+ definitions = [
141
+ { :long => 'aaa', :short => 'a', :argument => :forbidden }
142
+ ]
143
+
144
+ result = Cri::OptionParser.parse(input, definitions)
145
+
146
+ assert(result[:options][:aaa])
147
+ assert_equal([ 'foo', 'bar' ], result[:arguments])
148
+ end
149
+
150
+ def test_parse_with_short_valueful_option_with_missing_value
151
+ input = %w( foo -a )
152
+ definitions = [
153
+ { :long => 'aaa', :short => 'a', :argument => :required }
154
+ ]
155
+
156
+ result = nil
157
+
158
+ assert_raises(Cri::OptionParser::OptionRequiresAnArgumentError) do
159
+ result = Cri::OptionParser.parse(input, definitions)
160
+ end
161
+ end
162
+
163
+ def test_parse_with_short_combined_valueless_options
164
+ input = %w( foo -abc bar )
165
+ definitions = [
166
+ { :long => 'aaa', :short => 'a', :argument => :forbidden },
167
+ { :long => 'bbb', :short => 'b', :argument => :forbidden },
168
+ { :long => 'ccc', :short => 'c', :argument => :forbidden }
169
+ ]
170
+
171
+ result = Cri::OptionParser.parse(input, definitions)
172
+
173
+ assert(result[:options][:aaa])
174
+ assert(result[:options][:bbb])
175
+ assert(result[:options][:ccc])
176
+ assert_equal([ 'foo', 'bar' ], result[:arguments])
177
+ end
178
+
179
+ def test_parse_with_short_combined_valueful_options_with_missing_value
180
+ input = %w( foo -abc bar )
181
+ definitions = [
182
+ { :long => 'aaa', :short => 'a', :argument => :required },
183
+ { :long => 'bbb', :short => 'b', :argument => :forbidden },
184
+ { :long => 'ccc', :short => 'c', :argument => :forbidden }
185
+ ]
186
+
187
+ result = nil
188
+
189
+ assert_raises(Cri::OptionParser::OptionRequiresAnArgumentError) do
190
+ result = Cri::OptionParser.parse(input, definitions)
191
+ end
192
+ end
193
+
194
+ def test_parse_with_two_short_valueful_options
195
+ input = %w( foo -a -p 2 )
196
+ definitions = [
197
+ { :long => 'all', :short => 'a', :argument => :required },
198
+ { :long => 'port', :short => 'p', :argument => :required }
199
+ ]
200
+
201
+ result = nil
202
+
203
+ assert_raises(Cri::OptionParser::OptionRequiresAnArgumentError) do
204
+ result = Cri::OptionParser.parse(input, definitions)
205
+ end
206
+ end
207
+
208
+ def test_parse_with_short_valueless_option_with_optional_value
209
+ input = %w( foo -a )
210
+ definitions = [
211
+ { :long => 'aaa', :short => 'a', :argument => :optional }
212
+ ]
213
+
214
+ result = Cri::OptionParser.parse(input, definitions)
215
+
216
+ assert(result[:options][:aaa])
217
+ assert_equal([ 'foo' ], result[:arguments])
218
+ end
219
+
220
+ def test_parse_with_short_valueful_option_with_optional_value
221
+ input = %w( foo -a xxx )
222
+ definitions = [
223
+ { :long => 'aaa', :short => 'a', :argument => :optional }
224
+ ]
225
+
226
+ result = Cri::OptionParser.parse(input, definitions)
227
+
228
+ assert_equal({ :aaa => 'xxx' }, result[:options])
229
+ assert_equal([ 'foo' ], result[:arguments])
230
+ end
231
+
232
+ def test_parse_with_short_valueless_option_with_optional_value_and_more_options
233
+ input = %w( foo -a -b -c )
234
+ definitions = [
235
+ { :long => 'aaa', :short => 'a', :argument => :optional },
236
+ { :long => 'bbb', :short => 'b', :argument => :forbidden },
237
+ { :long => 'ccc', :short => 'c', :argument => :forbidden }
238
+ ]
239
+
240
+ result = Cri::OptionParser.parse(input, definitions)
241
+
242
+ assert(result[:options][:aaa])
243
+ assert(result[:options][:bbb])
244
+ assert(result[:options][:ccc])
245
+ assert_equal([ 'foo' ], result[:arguments])
246
+ end
247
+
248
+ def test_parse_with_single_hyphen
249
+ input = %w( foo - bar )
250
+ definitions = []
251
+
252
+ result = Cri::OptionParser.parse(input, definitions)
253
+
254
+ assert_equal({}, result[:options])
255
+ assert_equal([ 'foo', '-', 'bar' ], result[:arguments])
256
+ end
257
+
258
+ def test_parse_with_end_marker
259
+ input = %w( foo bar -- -x --yyy -abc )
260
+ definitions = []
261
+
262
+ result = Cri::OptionParser.parse(input, definitions)
263
+
264
+ assert_equal({}, result[:options])
265
+ assert_equal([ 'foo', 'bar', '-x', '--yyy', '-abc' ], result[:arguments])
266
+ end
267
+
268
+ def test_parse_with_end_marker_between_option_key_and_value
269
+ input = %w( foo --aaa -- zzz )
270
+ definitions = [
271
+ { :long => 'aaa', :short => 'a', :argument => :required }
272
+ ]
273
+
274
+ assert_raises(Cri::OptionParser::OptionRequiresAnArgumentError) do
275
+ result = Cri::OptionParser.parse(input, definitions)
276
+ end
277
+ end
278
+
279
+ end