list-tool 1.0.3 → 1.0.5
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 +4 -4
- data/README.md +4 -1
- data/lib/list_tool/app/commands/add_item_command.rb +20 -23
- data/lib/list_tool/app/commands/add_list_command.rb +19 -17
- data/lib/list_tool/app/commands/clear_list_command.rb +31 -0
- data/lib/list_tool/app/commands/command.rb +50 -0
- data/lib/list_tool/app/commands/delete_item_command.rb +19 -23
- data/lib/list_tool/app/commands/delete_list_command.rb +18 -19
- data/lib/list_tool/app/commands/help_command.rb +15 -13
- data/lib/list_tool/app/commands/rename_list_command.rb +24 -25
- data/lib/list_tool/app/commands/replace_item_command.rb +20 -21
- data/lib/list_tool/app/commands/show_items_command.rb +18 -20
- data/lib/list_tool/app/commands/show_lists_command.rb +16 -14
- data/lib/list_tool/app/commands/unknown_command.rb +16 -14
- data/lib/list_tool/app/commands/use_command.rb +18 -18
- data/lib/list_tool/app/commands/version_command.rb +16 -13
- data/lib/list_tool/app/commands.rb +3 -1
- data/lib/list_tool/list.rb +5 -0
- data/lib/list_tool/lister.rb +35 -23
- data/lib/list_tool/lister_data.rb +4 -0
- data/lib/list_tool/version.rb +1 -1
- data/spec/list_tool/app/commands/add_list_command_spec.rb +0 -6
- data/spec/list_tool/app/commands/clear_list_command_spec.rb +89 -0
- data/spec/list_tool/app/commands/command_spec.rb +101 -0
- data/spec/list_tool/app/commands_spec.rb +1 -1
- data/spec/list_tool/list_spec.rb +8 -0
- data/spec/list_tool/lister_data_spec.rb +8 -0
- data/spec/list_tool/lister_spec.rb +75 -61
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be84730bfcdb5b3ac055f621aa41cc3ebc931806
|
4
|
+
data.tar.gz: 8aca87d46e3b310f25e4e1a506af4327e1f5e643
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa3eb60d41ef20b9234efdcc728a48840e50d671270b8b301ee93c266050448b2114d94f8d96a4608090e0eb4b10ab802d2c033110a8d40580adb318a878421a
|
7
|
+
data.tar.gz: 8a4696d902bf523bbaf66a5a4db2080cc24542839175b842601bc61074b39944e29ccbd66649f3bb9c8697daa5b9e7b18136e434791f952c29922f904a425336
|
data/README.md
CHANGED
@@ -39,8 +39,10 @@ Require list-tool with `require 'list_tool'` command
|
|
39
39
|
lister.lists # => { 'todolist' => 3, 'wishlist' => 2 }
|
40
40
|
# (digits for item quantitiy in a list)
|
41
41
|
lister.list(list_index=nil) # => {name: 'list_name', items: ['item1', 'item2']}
|
42
|
+
lister.default_list # => {name: 'list_name', items: ['item1', 'item2']}
|
42
43
|
|
43
44
|
For **#list** method, if list index is not specified, it will return contents of default list.
|
45
|
+
For **#default_list** method, if default list is not set, it will return nil.
|
44
46
|
|
45
47
|
#### List management methods
|
46
48
|
|
@@ -71,7 +73,7 @@ ListerData class responds to all list management methods (**\*\_list**) and also
|
|
71
73
|
|
72
74
|
#### Errors
|
73
75
|
|
74
|
-
- all lister.\*_item methods
|
76
|
+
- all lister.\*_item methods raise **ListTool::ListNotFoundError** if list was not found.
|
75
77
|
- lister.list and lister.\*_list methods raise **ListTool::NoDefaultListError** if list index is not specified and default list is not set
|
76
78
|
- #save and #load methods may return **ListTool::FileAccessError** or **ListTool::FileNotFoundError**
|
77
79
|
- other errors are generally **ArgumentError** s
|
@@ -90,6 +92,7 @@ This gem provides console tool named '**clt**' ('console list tool'), which allo
|
|
90
92
|
al, add-list NAME Create list with NAME
|
91
93
|
rl, rename-list LIST, NAME Set LIST name to NAME
|
92
94
|
dl, del-list LIST Delete given LIST
|
95
|
+
cl, clear-list LIST Clear given LIST
|
93
96
|
sl, show-lists Print list of existing lists
|
94
97
|
u, use LIST Set default list
|
95
98
|
-h, --help Print this message
|
@@ -1,38 +1,35 @@
|
|
1
1
|
module ListTool
|
2
2
|
module App
|
3
3
|
|
4
|
-
class AddItemCommand
|
4
|
+
class AddItemCommand < Command
|
5
|
+
class << self
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def match? arg
|
8
|
+
['a', 'add-item'].include? arg
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
def parse argv
|
12
|
+
fail_if_not_an_array(argv)
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
item, list = argv.shift(2)
|
15
|
+
ensure_existence_of('item text' => item)
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
out[:list] = Integer(list) - 1 rescue raise(ArgumentError, 'list number must be an integer')
|
20
|
-
raise ArgumentError, "list number can't be less than 1" if out[:list] < 0
|
17
|
+
out = {text: item}
|
18
|
+
out[:list] = parse_list_number(list) if list
|
19
|
+
out
|
21
20
|
end
|
22
21
|
|
23
|
-
|
24
|
-
|
22
|
+
def execute options, lister
|
23
|
+
args = [ options.delete(:text) ]
|
24
|
+
args << options if options[:list]
|
25
|
+
raise(ListNotFoundError, 'no list with given number') if lister.add_item(*args).nil?
|
26
|
+
end
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
raise(ListNotFoundError, 'no list with given number') if lister.add_item(*args).nil?
|
30
|
-
end
|
28
|
+
def help
|
29
|
+
" a, add-item TEXT [LIST]\tAdd item with TEXT to given or default list"
|
30
|
+
end
|
31
31
|
|
32
|
-
def self.help
|
33
|
-
" a, add-item TEXT [LIST]\tAdd item with TEXT to given or default list"
|
34
32
|
end
|
35
|
-
|
36
33
|
end
|
37
34
|
|
38
35
|
end
|
@@ -1,29 +1,31 @@
|
|
1
1
|
module ListTool
|
2
2
|
module App
|
3
3
|
|
4
|
-
class AddListCommand
|
4
|
+
class AddListCommand < Command
|
5
|
+
class << self
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def match? arg
|
8
|
+
['al', 'add-list'].include? arg
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
name = argv.shift
|
13
|
-
raise ArgumentError, 'list name not specified' if name.nil?
|
14
|
-
raise ArgumentError, 'name is not a string' unless name.is_a? String
|
11
|
+
def parse argv
|
12
|
+
fail_if_not_an_array(argv)
|
15
13
|
|
16
|
-
|
17
|
-
|
14
|
+
name = argv.shift
|
15
|
+
ensure_existence_of("list name" => name)
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
end
|
17
|
+
{name: name}
|
18
|
+
end
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
def execute options, lister
|
21
|
+
raise(RuntimeError, "list creation failed") if lister.add_list(options[:name]).nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
def help
|
25
|
+
" al, add-list NAME\t\tCreate list with NAME"
|
26
|
+
end
|
26
27
|
|
28
|
+
end
|
27
29
|
end
|
28
30
|
|
29
31
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ListTool
|
2
|
+
module App
|
3
|
+
|
4
|
+
class ClearListCommand < Command
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def match? arg
|
8
|
+
['cl', 'clear-list'].include? arg
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse argv
|
12
|
+
fail_if_not_an_array(argv)
|
13
|
+
|
14
|
+
list = argv.shift
|
15
|
+
|
16
|
+
{list: parse_list_number!(list)}
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute options, lister
|
20
|
+
raise(ListNotFoundError, 'no list with given number') if lister.clear_list(options[:list]).nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
def help
|
24
|
+
" cl, clear-list LIST\t\tClear given LIST"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module ListTool
|
2
|
+
module App
|
3
|
+
|
4
|
+
class Command
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def parse_number str, name
|
9
|
+
index = Integer(str) - 1 rescue raise(ArgumentError, "#{name} number must be an integer")
|
10
|
+
raise ArgumentError, "#{name} number can't be less than 1" if index < 0
|
11
|
+
index
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def parse_item_number str
|
16
|
+
parse_number(str, "item")
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse_list_number str
|
20
|
+
parse_number(str, "list")
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def parse_item_number! str
|
25
|
+
raise ArgumentError, 'item number not specified' if str.nil?
|
26
|
+
parse_item_number(str)
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse_list_number! str
|
30
|
+
raise ArgumentError, 'list number not specified' if str.nil?
|
31
|
+
parse_list_number(str)
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
def ensure_existence_of hash
|
36
|
+
hash.each do |key, value|
|
37
|
+
raise ArgumentError, "#{key} not specified" if value.nil?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def fail_if_not_an_array arg
|
42
|
+
raise ArgumentError, "expected argument to be an array, #{arg.class} given" unless arg.is_a? Array
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -1,38 +1,34 @@
|
|
1
1
|
module ListTool
|
2
2
|
module App
|
3
3
|
|
4
|
-
class DeleteItemCommand
|
4
|
+
class DeleteItemCommand < Command
|
5
|
+
class << self
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def match? arg
|
8
|
+
['d', 'del-item'].include? arg
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
def parse argv
|
12
|
+
fail_if_not_an_array(argv)
|
12
13
|
|
13
|
-
|
14
|
-
raise ArgumentError, 'item number not specified' if item.nil?
|
14
|
+
item, list = argv.shift(2)
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
out[:list] = Integer(list) - 1 rescue raise(ArgumentError, 'list number must be an integer')
|
20
|
-
raise ArgumentError, "list number can't be less than 1" if out[:list] < 0
|
16
|
+
out = { item: parse_item_number!(item) }
|
17
|
+
out[:list] = parse_list_number(list) if list
|
18
|
+
out
|
21
19
|
end
|
22
20
|
|
23
|
-
|
24
|
-
|
21
|
+
def execute options, lister
|
22
|
+
args = [ options[:item] ]
|
23
|
+
args << {list: options[:list]} if options[:list]
|
24
|
+
raise(ListNotFoundError, 'no list with given number') if lister.delete_item(*args).nil?
|
25
|
+
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
raise(ListNotFoundError, 'no list with given number') if lister.delete_item(*args).nil?
|
30
|
-
end
|
27
|
+
def help
|
28
|
+
" d, del-item ITEM [LIST]\tDelete ITEM from given or default list"
|
29
|
+
end
|
31
30
|
|
32
|
-
def self.help
|
33
|
-
" d, del-item ITEM [LIST]\tDelete ITEM from given or default list"
|
34
31
|
end
|
35
|
-
|
36
32
|
end
|
37
33
|
|
38
34
|
end
|
@@ -1,31 +1,30 @@
|
|
1
1
|
module ListTool
|
2
2
|
module App
|
3
3
|
|
4
|
-
class DeleteListCommand
|
4
|
+
class DeleteListCommand < Command
|
5
|
+
class << self
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def match? arg
|
8
|
+
['dl', 'del-list'].include? arg
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
def parse argv
|
12
|
+
fail_if_not_an_array(argv)
|
13
|
+
|
14
|
+
list = argv.shift
|
15
|
+
|
16
|
+
{list: parse_list_number!(list)}
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
19
|
+
def execute options, lister
|
20
|
+
raise(ListNotFoundError, 'no list with given number') if lister.delete_list(options[:list]).nil?
|
21
|
+
end
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
23
|
+
def help
|
24
|
+
" dl, del-list LIST\t\tDelete given LIST"
|
25
|
+
end
|
24
26
|
|
25
|
-
def self.help
|
26
|
-
" dl, del-list LIST\t\tDelete given LIST"
|
27
27
|
end
|
28
|
-
|
29
28
|
end
|
30
29
|
|
31
30
|
end
|
@@ -1,24 +1,26 @@
|
|
1
1
|
module ListTool
|
2
2
|
module App
|
3
3
|
|
4
|
-
class HelpCommand
|
4
|
+
class HelpCommand < Command
|
5
|
+
class << self
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def match? arg
|
8
|
+
['h', '-h', 'help', '--help'].include? arg
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
def parse argv
|
12
|
+
{}
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
def execute options, lister
|
16
|
+
Printer.print_usage
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
def help
|
20
|
+
" -h, --help\t\t\tPrint this message"
|
21
|
+
end
|
21
22
|
|
23
|
+
end
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
@@ -1,33 +1,32 @@
|
|
1
1
|
module ListTool
|
2
2
|
module App
|
3
3
|
|
4
|
-
class RenameListCommand
|
4
|
+
class RenameListCommand < Command
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def match? arg
|
8
|
+
['rl', 'rename-list'].include? arg
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse argv
|
12
|
+
fail_if_not_an_array(argv)
|
13
|
+
|
14
|
+
list, name = argv.shift(2)
|
15
|
+
ensure_existence_of('new name' => name)
|
16
|
+
|
17
|
+
{ name: name, list: parse_list_number!(list) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute options, lister
|
21
|
+
args = [ options[:list], options[:name] ]
|
22
|
+
raise(ListNotFoundError, 'no list with given number') if lister.rename_list(*args).nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def help
|
26
|
+
" rl, rename-list LIST, NAME\tSet LIST name to NAME"
|
27
|
+
end
|
5
28
|
|
6
|
-
def self.match? arg
|
7
|
-
['rl', 'rename-list'].include? arg
|
8
29
|
end
|
9
|
-
|
10
|
-
def self.parse argv
|
11
|
-
raise ArgumentError, "expected argument to be an array, #{argv.class} given" unless argv.is_a? Array
|
12
|
-
list, name = argv.shift(2)
|
13
|
-
raise ArgumentError, 'list number not specified' if list.nil?
|
14
|
-
raise ArgumentError, 'new name not specified' if name.nil?
|
15
|
-
|
16
|
-
list = Integer(list) - 1 rescue raise(ArgumentError, 'list number must be an integer')
|
17
|
-
raise ArgumentError, "list number can't be less than 1" if list < 0
|
18
|
-
|
19
|
-
{name: name, list: list}
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.execute options, lister
|
23
|
-
args = [ options[:list], options[:name] ]
|
24
|
-
raise(ListNotFoundError, 'no list with given number') if lister.rename_list(*args).nil?
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.help
|
28
|
-
" rl, rename-list LIST, NAME\tSet LIST name to NAME"
|
29
|
-
end
|
30
|
-
|
31
30
|
end
|
32
31
|
|
33
32
|
end
|
@@ -1,33 +1,32 @@
|
|
1
1
|
module ListTool
|
2
2
|
module App
|
3
3
|
|
4
|
-
class ReplaceItemCommand
|
4
|
+
class ReplaceItemCommand < Command
|
5
|
+
class << self
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def match? arg
|
8
|
+
['r', 'replace-item'].include? arg
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
item, name = argv.shift(2)
|
13
|
-
raise ArgumentError, 'item number not specified' if item.nil?
|
14
|
-
raise ArgumentError, 'new name not specified' if name.nil?
|
15
|
-
|
16
|
-
item = Integer(item) - 1 rescue raise(ArgumentError, 'item number must be an integer')
|
17
|
-
raise ArgumentError, "item number can't be less than 1" if item < 0
|
11
|
+
def parse argv
|
12
|
+
fail_if_not_an_array(argv)
|
18
13
|
|
19
|
-
|
20
|
-
|
14
|
+
item, name = argv.shift(2)
|
15
|
+
ensure_existence_of('new name' => name)
|
21
16
|
|
22
|
-
|
23
|
-
|
24
|
-
raise(ItemNotFoundError, 'no item with given number') if lister.change_item(*args).nil?
|
25
|
-
end
|
17
|
+
{ name: name, item: parse_item_number!(item) }
|
18
|
+
end
|
26
19
|
|
27
|
-
|
28
|
-
|
29
|
-
|
20
|
+
def execute options, lister
|
21
|
+
args = [ options[:item], options[:name] ]
|
22
|
+
raise(ItemNotFoundError, 'no item with given number') if lister.change_item(*args).nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def help
|
26
|
+
" r, replace-item ITEM, TEXT\tSet ITEM text to TEXT"
|
27
|
+
end
|
30
28
|
|
29
|
+
end
|
31
30
|
end
|
32
31
|
|
33
32
|
end
|
@@ -1,34 +1,32 @@
|
|
1
1
|
module ListTool
|
2
2
|
module App
|
3
3
|
|
4
|
-
class ShowItemsCommand
|
4
|
+
class ShowItemsCommand < Command
|
5
|
+
class << self
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def match? arg
|
8
|
+
['s', 'show-items'].include? arg
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
def parse argv
|
12
|
+
fail_if_not_an_array(argv)
|
13
|
+
|
14
|
+
list = argv.shift
|
13
15
|
|
14
|
-
|
15
|
-
list = Integer( list ) - 1 rescue raise(ArgumentError, 'list number must be an integer')
|
16
|
-
raise ArgumentError, "list number can't be less than 1" if list < 0
|
16
|
+
list ? {list: parse_list_number(list)} : {}
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
def execute options, lister
|
20
|
+
items = options[:list].nil? ? lister.list() : lister.list(options[:list])
|
21
|
+
raise ListNotFoundError if items.nil?
|
22
|
+
Printer.print_items( items )
|
23
|
+
end
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
Printer.print_items( items )
|
26
|
-
end
|
25
|
+
def help
|
26
|
+
" s, show-items [LIST]\t\tPrint contents of default or given list"
|
27
|
+
end
|
27
28
|
|
28
|
-
def self.help
|
29
|
-
" s, show-items [LIST]\t\tPrint contents of default or given list"
|
30
29
|
end
|
31
|
-
|
32
30
|
end
|
33
31
|
|
34
32
|
end
|
@@ -1,25 +1,27 @@
|
|
1
1
|
module ListTool
|
2
2
|
module App
|
3
3
|
|
4
|
-
class ShowListsCommand
|
4
|
+
class ShowListsCommand < Command
|
5
|
+
class << self
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def match? arg
|
8
|
+
['sl', 'show-lists'].include? arg
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
def parse argv
|
12
|
+
{}
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
def execute options, lister
|
16
|
+
lists = lister.lists
|
17
|
+
Printer.print_lists(lists)
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
def help
|
21
|
+
" sl, show-lists\t\tPrint list of existing lists"
|
22
|
+
end
|
22
23
|
|
24
|
+
end
|
23
25
|
end
|
24
26
|
|
25
27
|
end
|
@@ -1,25 +1,27 @@
|
|
1
1
|
module ListTool
|
2
2
|
module App
|
3
3
|
|
4
|
-
class UnknownCommand
|
4
|
+
class UnknownCommand < Command
|
5
|
+
class << self
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
def match? arg
|
8
|
+
@unknown_command = arg
|
9
|
+
true
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
def parse argv
|
13
|
+
{}
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
def execute options, lister
|
17
|
+
raise UnknownCommandError, "unknown command: '#{@unknown_command}'"
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
def help
|
21
|
+
""
|
22
|
+
end
|
22
23
|
|
24
|
+
end
|
23
25
|
end
|
24
26
|
|
25
27
|
end
|