nanoc3 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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