cli 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -103,11 +103,16 @@ require 'yaml'
103
103
 
104
104
  options = CLI.new do
105
105
  description 'Generate blog posts in given Jekyll directory from input statistics'
106
- stdin :log_data, :cast => YAML, :description => 'statistic data in YAML format'
107
- option :location, :short => :l, :description => 'location name (ex. Dublin, Singapore, Califorina)'
108
- option :csv_dir, :short => :c, :cast => Pathname, :default => 'csv', :description => 'directory name where CSV file will be storred (relative to jekyll-dir)'
109
- argument :jekyll_dir, :cast => Pathname, :default => '/var/lib/vhs/jekyll', :description => 'directory where site source is located'
110
- end.parse!
106
+ stdin :log_data, :cast => YAML, :description => 'statistic data in YAML format'
107
+ option :location, :short => :l, :description => 'location name (ex. Dublin, Singapore, Califorina)'
108
+ option :csv_dir, :short => :c, :cast => Pathname, :default => 'csv', :description => 'directory name where CSV file will be storred (relative to jekyll-dir)'
109
+ argument :jekyll_dir, :cast => Pathname, :default => '/var/lib/vhs/jekyll', :description => 'directory where site source is located'
110
+ end.parse! do |options|
111
+ fail 'jekyll-dir is not a directory' unless options.jekyll_dir.directory?
112
+ fail '--csv-dir is not a directory (relative to jekyll-dir)' unless (options.jekyll_dir + options.csv_dir).directory?
113
+ end
114
+
115
+ p options
111
116
 
112
117
  # do your stuff
113
118
  ```
@@ -126,7 +131,7 @@ Example help message:
126
131
  Arguments:
127
132
  jekyll-dir - directory where site source is located
128
133
 
129
- With this example usage:
134
+ With this example usage (assuming /var/lib/vhs/jekyll/csv dir exist):
130
135
 
131
136
  examples/processor --location Singapore <<EOF
132
137
  :parser:
@@ -136,7 +141,22 @@ With this example usage:
136
141
 
137
142
  The `options` variable will contain:
138
143
 
139
- #<CLI::Values location="Singapore", stdin={:parser=>{:failures=>0, :successes=>41}}, jekyll_dir=#<Pathname:/var/lib/vhs/jekyll>, csv_dir=#<Pathname:csv>>
144
+ #<CLI::Values stdin={:parser=>{:successes=>41, :failures=>0}}, jekyll_dir=#<Pathname:/var/lib/vhs/jekyll>, csv_dir=#<Pathname:csv>, help=nil, location="Singapore">
145
+
146
+ Output if jekyll-dir does not exist:
147
+
148
+ Error: jekyll-dir is not a directory
149
+ Usage: processor [switches|options] [--] jekyll-dir < log-data
150
+ Generate blog posts in given Jekyll directory from input statistics
151
+ Input:
152
+ log-data - statistic data in YAML format
153
+ Switches:
154
+ --help (-h) - display this help message
155
+ Options:
156
+ --location (-l) - location name (ex. Dublin, Singapore, Califorina)
157
+ --csv-dir (-c) [csv] - directory name where CSV file will be storred (relative to jekyll-dir)
158
+ Arguments:
159
+ jekyll-dir [/var/lib/vhs/jekyll] - directory where site source is located
140
160
 
141
161
  ### Ls like utility
142
162
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "cli"
8
- s.version = "0.3.0"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jakub Pastuszek"]
12
- s.date = "2011-12-21"
12
+ s.date = "2011-12-30"
13
13
  s.description = "Provides DSL for command-line options, switches and arguments parser and stdin handling with generated usage printer"
14
14
  s.email = "jpastuszek@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -9,7 +9,10 @@ options = CLI.new do
9
9
  option :location, :short => :l, :description => 'location name (ex. Dublin, Singapore, Califorina)'
10
10
  option :csv_dir, :short => :c, :cast => Pathname, :default => 'csv', :description => 'directory name where CSV file will be storred (relative to jekyll-dir)'
11
11
  argument :jekyll_dir, :cast => Pathname, :default => '/var/lib/vhs/jekyll', :description => 'directory where site source is located'
12
- end.parse!
12
+ end.parse! do |options|
13
+ fail 'jekyll-dir is not a directory' unless options.jekyll_dir.directory?
14
+ fail '--csv-dir is not a directory (relative to jekyll-dir)' unless (options.jekyll_dir + options.csv_dir).directory?
15
+ end
13
16
 
14
17
  p options
15
18
 
data/lib/cli.rb CHANGED
@@ -87,6 +87,9 @@ class CLI
87
87
  super("failed to cast: '#{arg}' to type: #{cast_name}: #{error}")
88
88
  end
89
89
  end
90
+
91
+ class UsageError < ParsingError
92
+ end
90
93
  end
91
94
 
92
95
  class Values < OpenStruct
@@ -148,34 +151,19 @@ class CLI
148
151
 
149
152
  def switch(name, options = {})
150
153
  switch_dsl = DSL::Switch.new(name, options)
151
-
152
- raise ParserError::LongNameSpecifiedTwiceError.new('switch', switch_dsl) if @switches.has_long?(switch_dsl)
153
- raise ParserError::LongNameSpecifiedTwiceError.new('option and switch', switch_dsl) if @options.has_long?(switch_dsl)
154
- raise ParserError::ShortNameSpecifiedTwiceError.new('switch', switch_dsl) if @switches.has_short?(switch_dsl)
155
- raise ParserError::ShortNameSpecifiedTwiceError.new('option and switch', switch_dsl) if @options.has_short?(switch_dsl)
156
-
154
+ check_switch_collision!(switch_dsl)
157
155
  @switches << switch_dsl
158
156
  end
159
157
 
160
158
  def option(name, options = {})
161
159
  option_dsl = DSL::Option.new(name, options)
162
-
163
- raise ParserError::LongNameSpecifiedTwiceError.new('option', option_dsl) if @options.has_long?(option_dsl)
164
- raise ParserError::LongNameSpecifiedTwiceError.new('switch and option', option_dsl) if @switches.has_long?(option_dsl)
165
- raise ParserError::ShortNameSpecifiedTwiceError.new('option', option_dsl) if @options.has_short?(option_dsl)
166
- raise ParserError::ShortNameSpecifiedTwiceError.new('switch and option', option_dsl) if @switches.has_short?(option_dsl)
167
-
160
+ check_switch_collision!(option_dsl)
168
161
  @options << option_dsl
169
162
  end
170
163
 
171
164
  def options(name, options = {})
172
165
  option_dsl = DSL::Options.new(name, options)
173
-
174
- raise ParserError::LongNameSpecifiedTwiceError.new('option', option_dsl) if @options.has_long?(option_dsl)
175
- raise ParserError::LongNameSpecifiedTwiceError.new('switch and option', option_dsl) if @switches.has_long?(option_dsl)
176
- raise ParserError::ShortNameSpecifiedTwiceError.new('option', option_dsl) if @options.has_short?(option_dsl)
177
- raise ParserError::ShortNameSpecifiedTwiceError.new('switch and option', option_dsl) if @switches.has_short?(option_dsl)
178
-
166
+ check_switch_collision!(option_dsl)
179
167
  @options << option_dsl
180
168
  end
181
169
 
@@ -198,6 +186,15 @@ class CLI
198
186
  end
199
187
  end
200
188
 
189
+ # initialize values
190
+ @options.each do |o|
191
+ values.value(o, nil)
192
+ end
193
+
194
+ @switches.each do |o|
195
+ values.value(o, nil)
196
+ end
197
+
201
198
  # initialize multi options
202
199
  @options.multiple.each do |o|
203
200
  values.value(o, [])
@@ -274,6 +271,14 @@ class CLI
274
271
  stdout.write pp.version
275
272
  exit 0
276
273
  end
274
+
275
+ if block_given?
276
+ begin
277
+ yield pp
278
+ rescue RuntimeError => e
279
+ raise ParsingError::UsageError, e.message
280
+ end
281
+ end
277
282
  pp
278
283
  rescue ParsingError => pe
279
284
  usage!(pe, stderr)
@@ -353,5 +358,20 @@ class CLI
353
358
  io.write usage(msg)
354
359
  exit 42
355
360
  end
361
+
362
+ private
363
+
364
+ def check_switch_collision!(switch_dsl)
365
+ type = switch_dsl.class.name.downcase.sub(/.*::/, '')
366
+ {
367
+ 'switch' => @switches,
368
+ 'option' => @options
369
+ }.each_pair do |collection_type, collection|
370
+ what = (type == collection_type ? type : collection_type + ' and ' + type)
371
+
372
+ raise ParserError::LongNameSpecifiedTwiceError.new(what, switch_dsl) if collection.has_long?(switch_dsl)
373
+ raise ParserError::ShortNameSpecifiedTwiceError.new(what, switch_dsl) if collection.has_short?(switch_dsl)
374
+ end
375
+ end
356
376
  end
357
377
 
@@ -41,6 +41,47 @@ describe CLI do
41
41
  ps.code.should == 'hello'
42
42
  end
43
43
 
44
+ it "should return value structure where all values are set" do
45
+ h = CLI.new do
46
+ option :location, :short => :l
47
+ switch :debug
48
+ end.parse!([]).marshal_dump
49
+
50
+ h.member?(:location).should be_true
51
+ h[:location].should be_nil
52
+
53
+ h.member?(:debug).should be_true
54
+ h[:debug].should be_nil
55
+ end
56
+
57
+ it "should take a block that can be used to verify passed values" do
58
+ lambda {
59
+ ps = CLI.new do
60
+ option :location, :short => :l
61
+ switch :debug
62
+ switch :verbose
63
+ argument :code
64
+ end.parse!(['-l', 'singapore', '--debug', 'hello']) do |values|
65
+ fail '--debug can not be used with --verbose' if values.debug and values.verbose
66
+ end
67
+ }.should_not raise_error
68
+
69
+ out = stderr_read do
70
+ lambda {
71
+ ps = CLI.new do
72
+ option :location, :short => :l
73
+ switch :debug
74
+ switch :verbose
75
+ argument :code
76
+ end.parse!(['-l', 'singapore', '--debug', '--verbose', 'hello']) do |values|
77
+ fail '--debug can not be used with --verbose' if values.debug and values.verbose
78
+ end
79
+ }.should raise_error SystemExit
80
+ end
81
+ out.should include('Error: --debug can not be used with --verbose')
82
+ out.should include('Usage:')
83
+ end
84
+
44
85
  it "should exit displaying usage and error message on standard error on usage error" do
45
86
  out = stderr_read do
46
87
  lambda {
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cli
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 15
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 0.3.0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jakub Pastuszek
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-12-21 00:00:00 Z
18
+ date: 2011-12-30 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  type: :development