toodledo 1.3.5 → 1.3.8
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/History.txt +14 -0
- data/{README.txt → README.md} +61 -48
- data/Rakefile +60 -18
- data/lib/toodledo.rb +5 -4
- data/lib/toodledo/command_line/client.rb +893 -840
- data/lib/toodledo/command_line/parser_helper.rb +24 -1
- data/lib/toodledo/command_line/task_formatter.rb +174 -150
- data/lib/toodledo/priority.rb +1 -0
- data/lib/toodledo/repeat.rb +2 -0
- data/lib/toodledo/server_error.rb +17 -0
- data/lib/toodledo/session.rb +53 -18
- data/lib/toodledo/status.rb +37 -35
- data/lib/toodledo/task.rb +8 -3
- data/lib/toodledo/version.rb +11 -0
- data/test/client_test.rb +60 -12
- data/test/helper.rb +11 -0
- data/test/parser_helper_test.rb +36 -6
- data/test/session_test.rb +221 -39
- data/test/toodledo_functional_test.rb +33 -7
- data/toodledo.gemspec +97 -0
- metadata +35 -60
- data/Manifest.txt +0 -41
- data/lib/toodledo/item_not_found_error.rb +0 -8
@@ -9,6 +9,7 @@ module Toodledo
|
|
9
9
|
#
|
10
10
|
module ParserHelper
|
11
11
|
|
12
|
+
# TODO These regexps are highly repetitive. Refactor
|
12
13
|
FOLDER_REGEXP = /\*((\w+)|\[(.*?)\])/
|
13
14
|
|
14
15
|
GOAL_REGEXP = /\^((\w+)|\[(.*?)\])/
|
@@ -17,6 +18,10 @@ module Toodledo
|
|
17
18
|
|
18
19
|
PRIORITY_REGEXP = /!(top|high|medium|low|negative)/
|
19
20
|
|
21
|
+
DATE_REGEXP = /\#(([^\[]\S*)|\[(.*?)\])/
|
22
|
+
|
23
|
+
TAGS_REGEXP = /\%((\w+)|\[(.*?)\])/
|
24
|
+
|
20
25
|
# Note that level must exist at the beginning of the line
|
21
26
|
LEVEL_REGEXP = /^(life|medium|short)/
|
22
27
|
|
@@ -25,7 +30,9 @@ module Toodledo
|
|
25
30
|
FOLDER_REGEXP,
|
26
31
|
GOAL_REGEXP,
|
27
32
|
CONTEXT_REGEXP,
|
28
|
-
PRIORITY_REGEXP
|
33
|
+
PRIORITY_REGEXP,
|
34
|
+
DATE_REGEXP,
|
35
|
+
TAGS_REGEXP
|
29
36
|
]
|
30
37
|
|
31
38
|
# Parses a context in the format @Context or @[Spaced Context]
|
@@ -48,9 +55,25 @@ module Toodledo
|
|
48
55
|
return match_data if (match_data == nil)
|
49
56
|
return strip_brackets(match_data[1])
|
50
57
|
end
|
58
|
+
|
59
|
+
# Parses a date in the format #[2011-03-17]
|
60
|
+
def parse_date(input)
|
61
|
+
match_data = DATE_REGEXP.match(input)
|
62
|
+
return match_data if (match_data == nil)
|
63
|
+
return strip_brackets(match_data[1])
|
64
|
+
end
|
65
|
+
|
66
|
+
# Parses a list of tags in the format %[tag1 tag2 tag3]
|
67
|
+
# TODO Allow %tag1, tag2, tag3 ? (This is the format Toodledo's Twitter client uses)
|
68
|
+
def parse_tag(input)
|
69
|
+
match_data = TAGS_REGEXP.match(input)
|
70
|
+
return match_data if (match_data == nil)
|
71
|
+
return strip_brackets(match_data[1]).split(/\s+/)
|
72
|
+
end
|
51
73
|
|
52
74
|
# Parses priority in the format !priority (top, high, medium, low,
|
53
75
|
# negative)
|
76
|
+
# TODO Refactor using data-driven design
|
54
77
|
def parse_priority(input)
|
55
78
|
match_data = PRIORITY_REGEXP.match(input)
|
56
79
|
if (match_data == nil)
|
@@ -1,151 +1,175 @@
|
|
1
|
-
|
2
|
-
module Toodledo
|
3
|
-
module CommandLine
|
4
|
-
class TaskFormatter
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
if (task.
|
69
|
-
msg += "
|
70
|
-
end
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
when
|
126
|
-
|
127
|
-
when
|
128
|
-
|
129
|
-
when
|
130
|
-
|
131
|
-
when
|
132
|
-
|
133
|
-
when
|
134
|
-
|
135
|
-
when
|
136
|
-
|
137
|
-
when
|
138
|
-
|
139
|
-
|
140
|
-
'
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
1
|
+
|
2
|
+
module Toodledo
|
3
|
+
module CommandLine
|
4
|
+
class TaskFormatter
|
5
|
+
|
6
|
+
DUEDATE_BY = 0
|
7
|
+
DUEDATE_ON = 1
|
8
|
+
DUEDATE_AFTER = 2
|
9
|
+
DUEDATE_OPTIONALLY = 3
|
10
|
+
|
11
|
+
# Formats the task for a command line.
|
12
|
+
def format(task)
|
13
|
+
fancyp = '!' + readable_priority(task.priority)
|
14
|
+
|
15
|
+
msg = "<#{task.server_id}> -- #{fancyp}"
|
16
|
+
|
17
|
+
# TODO Only include [ ] if needed
|
18
|
+
if (task.folder != Folder::NO_FOLDER)
|
19
|
+
msg += " *[#{task.folder.name}]"
|
20
|
+
end
|
21
|
+
|
22
|
+
if (task.context != Context::NO_CONTEXT)
|
23
|
+
msg += " @[#{task.context.name}]"
|
24
|
+
end
|
25
|
+
|
26
|
+
if (task.goal != Goal::NO_GOAL)
|
27
|
+
msg += " ^[#{task.goal.name}]"
|
28
|
+
end
|
29
|
+
|
30
|
+
if (task.repeat != Repeat::NONE)
|
31
|
+
msg += " repeat[#{readable_repeat(task.repeat)}]"
|
32
|
+
end
|
33
|
+
|
34
|
+
if (task.duedate != nil)
|
35
|
+
fmt = '%m/%d/%Y %I:%M %p'
|
36
|
+
msg += " #[#{readable_duedatemodifier(task.duedatemodifier)}#{task.duedate.strftime(fmt)}]"
|
37
|
+
end
|
38
|
+
|
39
|
+
if (task.startdate != nil)
|
40
|
+
fmt = '%m/%d/%Y'
|
41
|
+
msg += " startdate[#{task.startdate.strftime(fmt)}]"
|
42
|
+
end
|
43
|
+
|
44
|
+
if (task.status != Status::NONE)
|
45
|
+
msg += " status[#{readable_status(task.status)}]"
|
46
|
+
end
|
47
|
+
|
48
|
+
if (task.star)
|
49
|
+
msg += " starred"
|
50
|
+
end
|
51
|
+
|
52
|
+
if (task.tag != nil)
|
53
|
+
msg += " %[#{task.tag}]"
|
54
|
+
end
|
55
|
+
|
56
|
+
if (task.parent_id != nil)
|
57
|
+
msg += " parent[#{task.parent.title}]"
|
58
|
+
end
|
59
|
+
|
60
|
+
if (task.length != nil)
|
61
|
+
msg += " length[#{task.length}]"
|
62
|
+
end
|
63
|
+
|
64
|
+
if (task.timer != nil)
|
65
|
+
msg += " timer[#{task.timer}]"
|
66
|
+
end
|
67
|
+
|
68
|
+
if (task.num_children != nil && task.num_children > 0)
|
69
|
+
msg += " children[#{task.num_children}]"
|
70
|
+
end
|
71
|
+
|
72
|
+
msg += " #{task.title}"
|
73
|
+
|
74
|
+
if (task.note != nil)
|
75
|
+
msg += "\n #{task.note}"
|
76
|
+
end
|
77
|
+
|
78
|
+
return msg
|
79
|
+
end
|
80
|
+
|
81
|
+
# TODO Refactor using symbols -- so much simpler to convert
|
82
|
+
def readable_priority(priority)
|
83
|
+
case priority
|
84
|
+
when Priority::TOP
|
85
|
+
return 'top'
|
86
|
+
when Priority::HIGH
|
87
|
+
return 'high'
|
88
|
+
when Priority::MEDIUM
|
89
|
+
return 'medium'
|
90
|
+
when Priority::LOW
|
91
|
+
return 'low'
|
92
|
+
when Priority::NEGATIVE
|
93
|
+
return 'negative'
|
94
|
+
else
|
95
|
+
return ''
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def readable_duedatemodifier(duedate_modifier)
|
100
|
+
# The modifier is passed in as [0..3] but may come back as
|
101
|
+
# <duedate modifier='?'>2011-06-30</duedate>
|
102
|
+
case duedate_modifier
|
103
|
+
when DUEDATE_BY then
|
104
|
+
return ''
|
105
|
+
when DUEDATE_ON then
|
106
|
+
return '='
|
107
|
+
when DUEDATE_AFTER then
|
108
|
+
return '>'
|
109
|
+
when DUEDATE_OPTIONALLY then
|
110
|
+
return '?'
|
111
|
+
else
|
112
|
+
return duedate_modifier
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
# Returns a string matching the numeric repeat code.
|
118
|
+
#
|
119
|
+
def readable_repeat(repeat)
|
120
|
+
case repeat
|
121
|
+
when Repeat::NONE
|
122
|
+
''
|
123
|
+
when Repeat::WEEKLY
|
124
|
+
"weekly"
|
125
|
+
when Repeat::MONTHLY
|
126
|
+
"monthly"
|
127
|
+
when Repeat::YEARLY
|
128
|
+
"yearly"
|
129
|
+
when Repeat::DAILY
|
130
|
+
"daily"
|
131
|
+
when Repeat::BIWEEKLY
|
132
|
+
"biweekly"
|
133
|
+
when Repeat::BIMONTHLY
|
134
|
+
"bimonthly"
|
135
|
+
when Repeat::SEMIANNUALLY
|
136
|
+
"semiannually"
|
137
|
+
when Repeat::QUARTERLY
|
138
|
+
"quarterly"
|
139
|
+
else
|
140
|
+
''
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
#
|
145
|
+
# Return a readable status given the numeric code.
|
146
|
+
#
|
147
|
+
def readable_status(status)
|
148
|
+
case status
|
149
|
+
when Status::NONE
|
150
|
+
'none'
|
151
|
+
when Status::NEXT_ACTION
|
152
|
+
'Next Action'
|
153
|
+
when Status::ACTIVE
|
154
|
+
'Active'
|
155
|
+
when Status::PLANNING
|
156
|
+
'Planning'
|
157
|
+
when Status::DELEGATED
|
158
|
+
'Delegated'
|
159
|
+
when Status::WAITING
|
160
|
+
'Waiting'
|
161
|
+
when Status::HOLD
|
162
|
+
'Hold'
|
163
|
+
when Status::POSTPONED
|
164
|
+
'Postponed'
|
165
|
+
when Status::SOMEDAY
|
166
|
+
'Someday'
|
167
|
+
when Status::CANCELLED
|
168
|
+
'Cancelled'
|
169
|
+
when Status::REFERENCE
|
170
|
+
'Reference'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
151
175
|
end
|
data/lib/toodledo/priority.rb
CHANGED
data/lib/toodledo/repeat.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
module Toodledo
|
5
5
|
class Repeat
|
6
6
|
|
7
|
+
# TODO Refactor
|
7
8
|
NONE = 0
|
8
9
|
WEEKLY = 1
|
9
10
|
MONTHLY = 2
|
@@ -32,6 +33,7 @@ module Toodledo
|
|
32
33
|
REPEAT_ARRAY.each{|value| yield(value)}
|
33
34
|
end
|
34
35
|
|
36
|
+
# TODO replace with include?
|
35
37
|
def self.valid?(input)
|
36
38
|
for repeat in REPEAT_ARRAY
|
37
39
|
if (repeat == input)
|
@@ -8,10 +8,27 @@ module Toodledo
|
|
8
8
|
|
9
9
|
end
|
10
10
|
|
11
|
+
#
|
12
|
+
# Thrown when a call to a server returns 'Invalid ID number'
|
13
|
+
#
|
14
|
+
class ItemNotFoundError < ServerError
|
15
|
+
|
16
|
+
end
|
17
|
+
|
11
18
|
# Thrown when the key is invalid (usually because we're using an old key or
|
12
19
|
# the expiration timed out for some reason)
|
13
20
|
class InvalidKeyError < ServerError
|
14
21
|
|
15
22
|
end
|
16
23
|
|
24
|
+
# Thrown when no key is specified at all.
|
25
|
+
class NoKeySpecifiedError < ServerError
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
# Thrown when too many requests have been made.
|
30
|
+
class ExcessiveTokenRequestsError < ServerError
|
31
|
+
|
32
|
+
end
|
33
|
+
|
17
34
|
end
|
data/lib/toodledo/session.rb
CHANGED
@@ -17,6 +17,11 @@ module Toodledo
|
|
17
17
|
#
|
18
18
|
class Session
|
19
19
|
|
20
|
+
INVALID_ID_MESSAGE = 'Invalid ID number'
|
21
|
+
INVALID_KEY_MESSAGE = 'key did not validate'
|
22
|
+
NO_KEY_SPECIFIED_MESSAGE = 'No Key Specified'
|
23
|
+
EXCESSIVE_TOKEN_MESSAGE = 'Excessive API token requests over the last 1 hour. This user is temporarily blocked.'
|
24
|
+
|
20
25
|
DEFAULT_API_URL = 'http://www.toodledo.com/api.php'
|
21
26
|
|
22
27
|
USER_AGENT = "Ruby/#{Toodledo::VERSION} (#{RUBY_PLATFORM})"
|
@@ -27,8 +32,8 @@ module Toodledo
|
|
27
32
|
'Keep-Alive' => '300'
|
28
33
|
}
|
29
34
|
|
30
|
-
# Make
|
31
|
-
FILE_EXPIRATION_TIME_IN_SECS = (60 * 60 * 4)
|
35
|
+
# Make file expiration be 4 hours.
|
36
|
+
FILE_EXPIRATION_TIME_IN_SECS = (60 * 60 * 4)
|
32
37
|
|
33
38
|
DATE_FORMAT = '%Y-%m-%d'
|
34
39
|
|
@@ -67,7 +72,7 @@ module Toodledo
|
|
67
72
|
return Digest::MD5.hexdigest(input_string)
|
68
73
|
end
|
69
74
|
|
70
|
-
# Connects to the server, asking for a new key that's good for
|
75
|
+
# Connects to the server, asking for a new key that's good for four hours.
|
71
76
|
# Optionally takes a base URL as a parameter. Defaults to DEFAULT_API_URL.
|
72
77
|
def connect(base_url = DEFAULT_API_URL, proxy = nil)
|
73
78
|
logger.debug("connect(#{base_url}, #{proxy.inspect})") if logger
|
@@ -105,10 +110,12 @@ module Toodledo
|
|
105
110
|
def disconnect()
|
106
111
|
logger.debug("disconnect()") if logger
|
107
112
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
113
|
+
if expired?
|
114
|
+
token_path = get_token_file(user_id)
|
115
|
+
if token_path
|
116
|
+
logger.debug("deleting token path(#{token_path})") if logger
|
117
|
+
File.delete(token_path)
|
118
|
+
end
|
112
119
|
end
|
113
120
|
|
114
121
|
@key = nil
|
@@ -126,10 +133,11 @@ module Toodledo
|
|
126
133
|
|
127
134
|
# Returns true if the session has expired.
|
128
135
|
def expired?
|
136
|
+
logger.debug("Expiration time #{@expiration_time} ") if logger
|
129
137
|
current_time = Time.now
|
130
138
|
has_expired = (@expiration_time != nil) && (current_time > @expiration_time)
|
131
139
|
if (has_expired)
|
132
|
-
logger.debug("#{@expiration_time} > #{current_time}, expired == true") if logger
|
140
|
+
logger.debug("Expiration time #{@expiration_time} > current time #{current_time}, expired == true") if logger
|
133
141
|
end
|
134
142
|
has_expired
|
135
143
|
end
|
@@ -240,21 +248,22 @@ module Toodledo
|
|
240
248
|
if (root_node.name == 'error')
|
241
249
|
error_text = root_node.text
|
242
250
|
case error_text
|
243
|
-
when
|
251
|
+
when INVALID_ID_MESSAGE then
|
244
252
|
raise Toodledo::ItemNotFoundError.new(error_text)
|
245
|
-
when
|
246
|
-
|
253
|
+
when INVALID_KEY_MESSAGE then
|
254
|
+
disconnect()
|
255
|
+
raise Toodledo::InvalidKeyError.new(error_text)
|
256
|
+
when NO_KEY_SPECIFIED_MESSAGE then
|
257
|
+
disconnect()
|
258
|
+
raise Toodledo::NoKeySpecifiedError.new(error_text)
|
259
|
+
when EXCESSIVE_TOKEN_MESSAGE
|
260
|
+
disconnect()
|
261
|
+
raise Toodledo::ExcessiveTokenRequestsError.new(error_text)
|
247
262
|
else
|
248
263
|
raise Toodledo::ServerError.new(error_text)
|
249
264
|
end
|
250
265
|
end
|
251
266
|
|
252
|
-
if (retry_error)
|
253
|
-
logger.debug("call(#{method}): invalid key, reconnecting") if logger
|
254
|
-
reconnect(@base_url, @proxy);
|
255
|
-
root_node = call(method, params);
|
256
|
-
end
|
257
|
-
|
258
267
|
return root_node
|
259
268
|
end
|
260
269
|
|
@@ -462,11 +471,14 @@ module Toodledo
|
|
462
471
|
# * star
|
463
472
|
# * status
|
464
473
|
# * startdate
|
474
|
+
# * tag
|
465
475
|
#
|
466
476
|
# Returns an array of tasks. This information is never cached.
|
467
477
|
def get_tasks(params={})
|
468
478
|
logger.debug("get_tasks(#{params.inspect})") if logger
|
469
479
|
myhash = {}
|
480
|
+
|
481
|
+
# TODO Very repetitious. Refactor
|
470
482
|
|
471
483
|
# * title : A text string up to 255 characters.
|
472
484
|
handle_string(myhash, params, :title)
|
@@ -548,6 +560,8 @@ module Toodledo
|
|
548
560
|
# * notcomp : Set to 1 to omit completed tasks. Omit variable, or set to 0
|
549
561
|
# to retrieve both completed and uncompleted tasks.
|
550
562
|
handle_boolean(myhash, params, :notcomp)
|
563
|
+
|
564
|
+
handle_tag(myhash, params)
|
551
565
|
|
552
566
|
result = call('getTasks', myhash, @key)
|
553
567
|
tasks = []
|
@@ -587,6 +601,7 @@ module Toodledo
|
|
587
601
|
# :bimonthly, :semiannually, :quarterly }
|
588
602
|
# length: a Number, number of minutes
|
589
603
|
# priority: one of { :negative, :low, :medium, :high, :top }
|
604
|
+
# tag: an Array of strings
|
590
605
|
#
|
591
606
|
# Returns: the id of the added task as a String.
|
592
607
|
def add_task(title, params={})
|
@@ -625,6 +640,8 @@ module Toodledo
|
|
625
640
|
# priority use the map to change from the symbol to the raw numeric value.
|
626
641
|
handle_priority(myhash, params)
|
627
642
|
|
643
|
+
handle_tag(myhash, params)
|
644
|
+
|
628
645
|
# Handle the star.
|
629
646
|
handle_boolean(myhash, params, :star)
|
630
647
|
|
@@ -653,6 +670,7 @@ module Toodledo
|
|
653
670
|
# * length : An integer representing the number of minutes that the task will take to complete.
|
654
671
|
# * priority : Use the PRIORITY_MAP with the relevant symbol here.
|
655
672
|
# * note : A text string.
|
673
|
+
# * tag: An Array of Strings (tags)
|
656
674
|
def edit_task(id, params = {})
|
657
675
|
logger.debug("edit_task(#{id}, #{params.inspect})") if logger
|
658
676
|
raise "Nil id" if (id == nil)
|
@@ -691,6 +709,8 @@ module Toodledo
|
|
691
709
|
|
692
710
|
# priority use the map to change from the symbol to the raw numeric value.
|
693
711
|
handle_priority(myhash, params)
|
712
|
+
|
713
|
+
handle_tag(myhash, params)
|
694
714
|
|
695
715
|
handle_string(myhash, params, :note)
|
696
716
|
|
@@ -1075,7 +1095,7 @@ module Toodledo
|
|
1075
1095
|
def handle_number(myhash, params, symbol)
|
1076
1096
|
value = params[symbol]
|
1077
1097
|
if (value != nil)
|
1078
|
-
if (value.kind_of?
|
1098
|
+
if (value.kind_of? Integer)
|
1079
1099
|
myhash.merge!({ symbol => value.to_s})
|
1080
1100
|
end
|
1081
1101
|
end
|
@@ -1122,6 +1142,21 @@ module Toodledo
|
|
1122
1142
|
myhash.merge!({ symbol => value })
|
1123
1143
|
end
|
1124
1144
|
|
1145
|
+
|
1146
|
+
def handle_tag(myhash, params)
|
1147
|
+
value = params[:tag]
|
1148
|
+
if (value == nil)
|
1149
|
+
return
|
1150
|
+
end
|
1151
|
+
|
1152
|
+
case value
|
1153
|
+
when Array
|
1154
|
+
value = value.join(' ')
|
1155
|
+
end
|
1156
|
+
|
1157
|
+
myhash.merge!({ :tag => value })
|
1158
|
+
end
|
1159
|
+
|
1125
1160
|
def handle_time(myhash, params, symbol)
|
1126
1161
|
value = params[symbol]
|
1127
1162
|
if (value == nil)
|