optiflag 0.6
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.
- data/ReleaseNotes.txt +110 -0
- data/doc/example/example_1.rb +30 -0
- data/doc/example/example_1_1.rb +27 -0
- data/doc/example/example_1_2.rb +28 -0
- data/doc/example/example_2.rb +28 -0
- data/doc/example/example_2_1.rb +23 -0
- data/doc/example/example_2_2.rb +31 -0
- data/doc/example/example_2_3.rb +37 -0
- data/doc/example/example_2_4.rb +37 -0
- data/doc/example/example_2_5.rb +28 -0
- data/doc/example/example_2_6.rb +22 -0
- data/doc/example/example_3.rb +33 -0
- data/doc/example/example_4.rb +12 -0
- data/doc/example/example_5.rb +26 -0
- data/doc/example/example_6.rb +17 -0
- data/doc/example/example_7.rb +39 -0
- data/lib/optiflag.rb +860 -0
- data/optiflag.gemspec +13 -0
- data/test/tc_advanced_usage_helping.rb +42 -0
- data/test/tc_basic_alternate_forms.rb +30 -0
- data/test/tc_basic_char_flags.rb +103 -0
- data/test/tc_basic_optional_flag.rb +74 -0
- data/test/tc_basic_parsing.rb +51 -0
- data/test/tc_basic_usage_helping.rb +40 -0
- data/test/tc_basic_value_validation.rb +40 -0
- data/test/tc_bug_one.rb +25 -0
- data/test/tc_bug_two.rb +33 -0
- data/test/tc_change_symbols.rb +61 -0
- data/test/tc_enumerated_value_validation.rb +35 -0
- data/test/tc_flagall.rb +17 -0
- data/test/tc_flagless_arg.rb +37 -0
- data/test/tc_keyword.rb +37 -0
- data/test/tc_values_as_hash.rb +46 -0
- metadata +95 -0
data/ReleaseNotes.txt
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
---------------------------------------------------------------------------------
|
2
|
+
RELEASE 0.6 (Character Flags FINALLY)
|
3
|
+
---------------------------------------------------------------------------------
|
4
|
+
* added top-level flag declaration 'character_flag'
|
5
|
+
* made 'keyword' an optional by default
|
6
|
+
|
7
|
+
---------------------------------------------------------------------------------
|
8
|
+
RELEASE 0.5 (Features getting close to done)
|
9
|
+
---------------------------------------------------------------------------------
|
10
|
+
* added top-level flag declaration 'keyword'
|
11
|
+
* added unit test for this new functionality
|
12
|
+
* added automatically generated ?methods? for
|
13
|
+
alternate forms of flags
|
14
|
+
* made sure not to try generating methods
|
15
|
+
from non alphabetic flag names
|
16
|
+
* Added ability to acces values via hash lookup
|
17
|
+
(see Example 4)
|
18
|
+
|
19
|
+
---------------------------------------------------------------------------------
|
20
|
+
RELEASE 0.4 (Internal Maintenance Mainly)
|
21
|
+
---------------------------------------------------------------------------------
|
22
|
+
* Added internal version number
|
23
|
+
* Addded experimental ability to define flags off of the fields of a
|
24
|
+
pre-existing object. Some problems with visibility will keep this
|
25
|
+
experimental for now. See the method using_object
|
26
|
+
* Spelling fix ups
|
27
|
+
* Aliased flag_properties to properties. For ease of use.
|
28
|
+
* Added some large section-defining comments
|
29
|
+
* Renamed internal EachFlag variables from 'foo_val' to 'the_foo'
|
30
|
+
* Coined terminology for Application Programmer's Syntax
|
31
|
+
-- Top-Level Flag Declarers
|
32
|
+
-- Clause-Level Flag Modifier
|
33
|
+
|
34
|
+
---------------------------------------------------------------------------------
|
35
|
+
RELEASE 0.3
|
36
|
+
---------------------------------------------------------------------------------
|
37
|
+
* Fixed a bug that globally changed the state of all modules
|
38
|
+
when a user chose to use the
|
39
|
+
'module SomeThing extend OptiFlag::Flagset(:flag_symbol => "/")'
|
40
|
+
syntax. Required some singleton class trickeration and module cloning.
|
41
|
+
* Changed all references from OptiFlag::FlagestDefinitions to
|
42
|
+
OptiFlag::Flagset which is shorter and therefore easier to use
|
43
|
+
(not everyone has dynamic-abbrev in emacs enabled to make typing easy)
|
44
|
+
* Started changing the design of printing help so that users can
|
45
|
+
register help-formatting bundles to do their own rendering of usage
|
46
|
+
and error messages
|
47
|
+
* Changed the functionality of the 'usage_flag' option to be of
|
48
|
+
either zero or one arity. With standard zero arity, the help will
|
49
|
+
print out the standard help/usage message. With an arity of one,
|
50
|
+
the help/usage flag will assume that the argument is another flag
|
51
|
+
for which we will print extended usage (example: '-h dir' will print
|
52
|
+
the help message just for the '-dir' flag)
|
53
|
+
* Fixed another nasty global-state bug (the perils of using '@' syntax
|
54
|
+
with modules)... This one wasn't needed -- it would only affect those
|
55
|
+
people who chose to parse an array of strings a 2nd and 3rd time, and
|
56
|
+
I was considering mandating that the parse method could only be called
|
57
|
+
once... but since my tests relied on multiple parses, I decided to fix
|
58
|
+
it just to make the test suites continually easy to write.
|
59
|
+
* Added a new top-level declarative form: 'optional_switch_flag' which
|
60
|
+
is an optional flag with zero arity. (I needed this one for myself)
|
61
|
+
* A few more tests were added:
|
62
|
+
-- tc_basic_optional_flag.rb
|
63
|
+
-- tc_bug_two.rb
|
64
|
+
* Wrote some XSLT and a ruby-script to autogenerate the site at
|
65
|
+
http://optiflag.rubyforge.org
|
66
|
+
* Added a warning generation system for things that are not errors
|
67
|
+
-- extra parameters left over (implemented)
|
68
|
+
-- potential consumption of an optional flag as value
|
69
|
+
to a flag with >0 arity. (example: '-dir -verbose' where
|
70
|
+
'-dir' takes on argument and '-verbose' is optional. In this
|
71
|
+
case the '-verbose' would be consumed as the value unless
|
72
|
+
warning mode was on)
|
73
|
+
|
74
|
+
|
75
|
+
---------------------------------------------------------------------------------
|
76
|
+
RELEASE 0.2 (5/23/2006)
|
77
|
+
---------------------------------------------------------------------------------
|
78
|
+
* The following features are implemented:
|
79
|
+
* required and optional flags
|
80
|
+
* ability to change flag arity from 0 to N
|
81
|
+
* flag value validation
|
82
|
+
-- by set membership
|
83
|
+
-- by regular expression
|
84
|
+
* flag value translation (pre and post validation)
|
85
|
+
* auto help
|
86
|
+
* auto error checking
|
87
|
+
* usage and extended usage flags
|
88
|
+
* universal flag symbol change
|
89
|
+
* case by case flag symbol change (both normal and long form)
|
90
|
+
* alternate forms for normal flag
|
91
|
+
* alternate form for long form flag
|
92
|
+
* auto-generated property-type methods added to ARGV for
|
93
|
+
flag values post-parsing
|
94
|
+
* sub-clause verbs
|
95
|
+
-- 'description'
|
96
|
+
-- 'arity'
|
97
|
+
-- 'no_args'
|
98
|
+
-- 'one_arg'
|
99
|
+
-- 'two_args'
|
100
|
+
-- 'long_form'
|
101
|
+
-- 'translate'
|
102
|
+
-- 'value_matches'
|
103
|
+
-- 'value_in_set'
|
104
|
+
-- 'required'
|
105
|
+
-- 'optional'
|
106
|
+
-- 'alternate_forms'
|
107
|
+
-- 'long_form'
|
108
|
+
-- 'dash_symbol'
|
109
|
+
-- 'long_dash_symbol'
|
110
|
+
* Added a series of Example Files
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'optiflag'
|
2
|
+
|
3
|
+
# Example 1: Four required flags
|
4
|
+
module Example extend OptiFlag::Flagset
|
5
|
+
flag "dir"
|
6
|
+
flag "log"
|
7
|
+
flag "username"
|
8
|
+
flag "password"
|
9
|
+
end
|
10
|
+
|
11
|
+
result = Example::parse(ARGV)
|
12
|
+
if result.errors?
|
13
|
+
result.errors.divulge_problems
|
14
|
+
exit
|
15
|
+
end
|
16
|
+
|
17
|
+
# Some code to _use_ the values
|
18
|
+
puts "User has input:#{ result.flag_value.dir } for dir"
|
19
|
+
puts "User has input:#{ result.flag_value.log } for log"
|
20
|
+
puts "User has input:#{ result.flag_value.username } for username"
|
21
|
+
puts "User has input:#{ result.flag_value.password } for password"
|
22
|
+
|
23
|
+
puts "The variable 'result' is actually just a copy of ARGV"
|
24
|
+
puts "that has been extend to hold the return variables:"
|
25
|
+
puts "See: #{ result.join(', ') }"
|
26
|
+
|
27
|
+
|
28
|
+
# Try the following inputs
|
29
|
+
# ruby example_1.rb
|
30
|
+
#h# ruby example_1.rb -log logdirectory -dir directory -username me -password fluffy
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'optiflag'
|
2
|
+
|
3
|
+
# Example 1.1:
|
4
|
+
# Variation 1: add a method 'handle_errors_and_help' to autoparse, check, and augment ARGV
|
5
|
+
module Example extend OptiFlag::Flagset
|
6
|
+
flag "dir"
|
7
|
+
flag "log"
|
8
|
+
flag "username"
|
9
|
+
flag "password"
|
10
|
+
|
11
|
+
handle_errors_and_help
|
12
|
+
end
|
13
|
+
|
14
|
+
# Some code to _use_ the values
|
15
|
+
puts "User has input:#{ ARGV.flag_value.dir } for dir"
|
16
|
+
puts "User has input:#{ ARGV.flag_value.log } for log"
|
17
|
+
puts "User has input:#{ ARGV.flag_value.username } for username"
|
18
|
+
puts "User has input:#{ ARGV.flag_value.password } for password"
|
19
|
+
|
20
|
+
puts " The variable ARGV has been extend to hold the return variables."
|
21
|
+
|
22
|
+
# Try the following inputs
|
23
|
+
## Breaks:
|
24
|
+
#h# ruby example_1_1.rb
|
25
|
+
## Works:
|
26
|
+
#h# ruby example_1_1.rb -log logdirectory -dir directory -username me -password fluffy
|
27
|
+
# ruby example_1_1.rb --log logdirectory --dir directory --username me --password fluffy
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'optiflag'
|
2
|
+
|
3
|
+
# Example 1.2:
|
4
|
+
# Variation 2: Changing the universal short-form default symbol from '-' to '/'
|
5
|
+
module Example extend OptiFlag::Flagset(:flag_symbol => "/")
|
6
|
+
flag "dir"
|
7
|
+
flag "log"
|
8
|
+
flag "username"
|
9
|
+
flag "password"
|
10
|
+
|
11
|
+
handle_errors_and_help
|
12
|
+
end
|
13
|
+
|
14
|
+
# Some code to _use_ the values
|
15
|
+
puts "User has input:#{ ARGV.flag_value.dir } for dir"
|
16
|
+
puts "User has input:#{ ARGV.flag_value.log } for log"
|
17
|
+
puts "User has input:#{ ARGV.flag_value.username } for username"
|
18
|
+
puts "User has input:#{ ARGV.flag_value.password } for password"
|
19
|
+
|
20
|
+
|
21
|
+
# Try the following inputs
|
22
|
+
## Breaks:
|
23
|
+
# ruby example_1_2.rb
|
24
|
+
#h# ruby example_1_2.rb -log logdirectory -dir directory -username me -password fluffy
|
25
|
+
## Works:
|
26
|
+
#h# ruby example_1_2.rb /log logdirectory /dir directory /username me /password fluffy
|
27
|
+
# ruby example_1_2.rb --log logdirectory --dir directory --username me --password fluffy
|
28
|
+
#h# ruby example_1_2.rb --log logdirectory /dir directory --username me /password fluffy
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'optiflag'
|
2
|
+
$log = "c:/log"
|
3
|
+
|
4
|
+
# Example 2: Adding an optional flag and a usage flag
|
5
|
+
module Example extend OptiFlag::Flagset
|
6
|
+
flag "dir"
|
7
|
+
optional_flag "log"
|
8
|
+
flag "username"
|
9
|
+
flag "password"
|
10
|
+
usage_flag "h","help","?"
|
11
|
+
|
12
|
+
handle_errors_and_help
|
13
|
+
end
|
14
|
+
|
15
|
+
if ARGV.flag_value.log? # note the question mark '?'
|
16
|
+
$log = ARGV.flag_value.log
|
17
|
+
puts "User input: #{ $log } for log via the command-line"
|
18
|
+
else
|
19
|
+
puts "User did NOT input log via the command-line"
|
20
|
+
end
|
21
|
+
|
22
|
+
#h# ruby example_2.rb --dir directory --username me --password fluffy
|
23
|
+
#h# ruby example_2.rb --dir directory --username me --password fluffy --log c:/tmp/log
|
24
|
+
# ruby example_2.rb -dir directory -username me -password fluffy -log c:/tmp/log
|
25
|
+
#h# ruby example_2.rb -h
|
26
|
+
#h# ruby example_2.rb -?
|
27
|
+
# ruby example_2.rb -help
|
28
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'optiflag'
|
2
|
+
|
3
|
+
# Example 2.1:
|
4
|
+
# Variation 1: Using an extended usage flag
|
5
|
+
module Example extend OptiFlag::Flagset
|
6
|
+
flag "dir"
|
7
|
+
optional_flag "log"
|
8
|
+
flag "username"
|
9
|
+
flag "password"
|
10
|
+
usage_flag "h","help","?"
|
11
|
+
extended_help_flag "superhelp"
|
12
|
+
|
13
|
+
handle_errors_and_help
|
14
|
+
end
|
15
|
+
|
16
|
+
#h# ruby example_2_1.rb -superhelp --dir directory --username me --password fluffy
|
17
|
+
# ruby example_2_1.rb -superhelp --dir directory --username me --password fluffy
|
18
|
+
# ruby example_2_1.rb -superhelp --dir directory --username me --password fluffy
|
19
|
+
# ruby example_2_1.rb -superhelp --dir directory --username me
|
20
|
+
# ruby example_2_1.rb -superhelp --dir directory
|
21
|
+
# ruby example_2_1.rb -superhelp
|
22
|
+
#h# ruby example_2_1.rb --superhelp
|
23
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'optiflag'
|
2
|
+
|
3
|
+
# Example 2.2:
|
4
|
+
# Variation 2: Adding descriptions to the flags (will appear in extended help)
|
5
|
+
### NOTE how 'description' can be nested in a block or used as a symbol key
|
6
|
+
module Example extend OptiFlag::Flagset
|
7
|
+
flag "dir" do
|
8
|
+
description "The Appliction Directory"
|
9
|
+
end
|
10
|
+
optional_flag "log" do
|
11
|
+
description "The directory in which to find the log files"
|
12
|
+
end
|
13
|
+
flag "username", :description => "Database username." # alternate form
|
14
|
+
flag "password" do
|
15
|
+
description "Database password."
|
16
|
+
end
|
17
|
+
usage_flag "h","help","?"
|
18
|
+
extended_help_flag "superhelp"
|
19
|
+
|
20
|
+
handle_errors_and_help
|
21
|
+
end
|
22
|
+
|
23
|
+
## Works (triggers extended help):
|
24
|
+
# ruby example_2_2.rb -superhelp --dir directory --username me --password fluffy
|
25
|
+
# ruby example_2_2.rb -superhelp --dir directory --username me --password fluffy
|
26
|
+
# ruby example_2_2.rb -superhelp --dir directory --username me --password fluffy
|
27
|
+
# ruby example_2_2.rb -superhelp --dir directory --username me
|
28
|
+
# ruby example_2_2.rb -superhelp --dir directory
|
29
|
+
# ruby example_2_2.rb -superhelp
|
30
|
+
#h# ruby example_2_2.rb --superhelp
|
31
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'optiflag'
|
2
|
+
|
3
|
+
# Example 2.3:
|
4
|
+
# Variation 3: Adding alternate forms and long forms
|
5
|
+
module Example extend OptiFlag::Flagset
|
6
|
+
flag "dir" do
|
7
|
+
alternate_forms "directory","D","d"
|
8
|
+
description "The Appliction Directory"
|
9
|
+
end
|
10
|
+
optional_flag "log" do
|
11
|
+
description "The directory in which to find the log files"
|
12
|
+
long_form "logging-directory" # long form is keyed after the '--' symbol
|
13
|
+
end
|
14
|
+
flag "username", :description => "Database username." # alternate form
|
15
|
+
flag "password" do
|
16
|
+
description "Database password."
|
17
|
+
end
|
18
|
+
usage_flag "h","help","?"
|
19
|
+
extended_help_flag "superhelp"
|
20
|
+
|
21
|
+
handle_errors_and_help
|
22
|
+
end
|
23
|
+
|
24
|
+
# Some code to _use_ the values
|
25
|
+
puts "User has input: #{ ARGV.flag_value.dir } for dir"
|
26
|
+
puts "User has input: #{ ARGV.flag_value.username } for username"
|
27
|
+
puts "User has input: #{ ARGV.flag_value.password } for password"
|
28
|
+
if ARGV.flag_value.log?
|
29
|
+
puts "User has input: #{ARGV.flag_value.log } for log"
|
30
|
+
end
|
31
|
+
|
32
|
+
# Try the following inputs
|
33
|
+
#h# ruby example_2_3.rb -dir directory -username me -password fluffy
|
34
|
+
# ruby example_2_3.rb -D directory -username me -password fluffy
|
35
|
+
#h# ruby example_2_3.rb -d directory -username me -password fluffy
|
36
|
+
## Works (uses different long form for log):
|
37
|
+
#h# ruby example_2_3.rb -d directory -username me -password fluffy --logging-directory c:/tmp/log
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'optiflag'
|
2
|
+
|
3
|
+
# Example 2_4:
|
4
|
+
# Variation 4: Selectively changing the symbol for a flag, and change the arity to be no-args
|
5
|
+
module Example extend OptiFlag::Flagset
|
6
|
+
flag "dir" do
|
7
|
+
alternate_forms "directory","D","d"
|
8
|
+
description "The Appliction Directory"
|
9
|
+
end
|
10
|
+
optional_flag "log" do
|
11
|
+
description "The directory in which to find the log files"
|
12
|
+
long_form "logging-directory"
|
13
|
+
end
|
14
|
+
flag "username", :description => "Database username."
|
15
|
+
flag "password" do
|
16
|
+
description "Database password."
|
17
|
+
end
|
18
|
+
optional_flag "delete" do
|
19
|
+
no_args # stating that this flag accepts no arguments
|
20
|
+
description "Delete database when done. Use carefully!!"
|
21
|
+
dash_symbol "!" # changing the symbol here
|
22
|
+
long_dash_symbol "!!" # changing its long form here
|
23
|
+
end
|
24
|
+
usage_flag "h","help","?"
|
25
|
+
extended_help_flag "superhelp"
|
26
|
+
|
27
|
+
handle_errors_and_help
|
28
|
+
end
|
29
|
+
|
30
|
+
if ARGV.flag_value.delete?
|
31
|
+
# super dangerous code to delete the database....
|
32
|
+
puts "Special DELETE flag invoked with special flag-symbol"
|
33
|
+
end
|
34
|
+
|
35
|
+
## Works (uses delete flag with different switch symbol):
|
36
|
+
#h# ruby example_2_4.rb -d directory -username me -password fluffy !!delete --logging-directory c:/tmp/log
|
37
|
+
# ruby example_2_4.rb -d directory -username me -password fluffy !delete --logging-directory c:/tmp/log
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'optiflag'
|
2
|
+
|
3
|
+
# Example 2.5:
|
4
|
+
# Variation 5: User can get help on a specific flag.
|
5
|
+
module Example extend OptiFlag::Flagset
|
6
|
+
flag "dir"
|
7
|
+
optional_flag "log" do
|
8
|
+
description "The directory into which log files will be written"
|
9
|
+
end
|
10
|
+
flag "username" do
|
11
|
+
description "A Zeta-Blub Appliction Username."
|
12
|
+
end
|
13
|
+
flag "password" do
|
14
|
+
description "Your IT issued password. Don't forget it!"
|
15
|
+
end
|
16
|
+
usage_flag "h","help","?"
|
17
|
+
|
18
|
+
handle_errors_and_help
|
19
|
+
end
|
20
|
+
|
21
|
+
## Normal mode:
|
22
|
+
# ruby example_2_5.rb -help
|
23
|
+
# ruby example_2_5.rb -?
|
24
|
+
# ruby example_2_5.rb -h
|
25
|
+
## Help on something specific:
|
26
|
+
#h# ruby example_2_5.rb -help username
|
27
|
+
#h# ruby example_2_5.rb -? log
|
28
|
+
#h# ruby example_2_5.rb -h password
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'optiflag'
|
2
|
+
|
3
|
+
# Example 2.6:
|
4
|
+
# Variation 6: Using the optional switch flag, a zero argument optional flag
|
5
|
+
module Example extend OptiFlag::Flagset
|
6
|
+
flag "dir"
|
7
|
+
optional_switch_flag "clear"
|
8
|
+
|
9
|
+
handle_errors_and_help
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
flag = ARGV.flag_value
|
15
|
+
if flag.clear?
|
16
|
+
puts "The optional switch flag -clear has been invoked"
|
17
|
+
else
|
18
|
+
puts "The optional switch flag -clear was NOT invoked"
|
19
|
+
end
|
20
|
+
|
21
|
+
#h# ruby example_2_6.rb -dir c:/dir
|
22
|
+
#h# ruby example_2_6.rb -clear -dir c:/dir
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'optiflag'
|
2
|
+
|
3
|
+
# Example 3: Adding validation rules to the value of an input flag
|
4
|
+
## See the flags : "mode", "run_date", and "connection"
|
5
|
+
module Example extend OptiFlag::Flagset
|
6
|
+
flag "dir"
|
7
|
+
flag "connection" do
|
8
|
+
value_matches ["Connection string must be of the form username/password@servicename", /^\b.+\b\/\b.+@.+$/ ]
|
9
|
+
end
|
10
|
+
optional_flag "mode" do
|
11
|
+
value_in_set ["read","write","execute"]
|
12
|
+
end
|
13
|
+
optional_flag "run_date" do
|
14
|
+
value_matches ["run_date must be of the form mm/DD/YY",/^[0-9]{2}\/[0-9]{2}\/[0-9]{2,4}$/]
|
15
|
+
end
|
16
|
+
usage_flag "h","help","?"
|
17
|
+
|
18
|
+
handle_errors_and_help
|
19
|
+
end
|
20
|
+
|
21
|
+
flag = ARGV.flag_value
|
22
|
+
|
23
|
+
puts "Mode flag is #{ flag.mode }" if flag.mode?
|
24
|
+
puts "Run Date flag is #{ flag.run_date }" if flag.run_date?
|
25
|
+
puts "Connection flag is #{ flag.connection }" if flag.connection?
|
26
|
+
|
27
|
+
|
28
|
+
# Try the following inputs
|
29
|
+
#h# ruby example_3.rb -dir directory -connection deklund/password@HAL.FBI.GOV -mode read -run_date 12/23/2005
|
30
|
+
## Breaks (breaks a validation rule)
|
31
|
+
#h# ruby example_3.rb -dir directory -connection 78GCTHR.com
|
32
|
+
#h# ruby example_3.rb -dir directory -connection deklund/password@HAL.FBI.GOV -mode CRACK! -run_date 12/23/2005
|
33
|
+
|