doing 2.0.9.pre → 2.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardoc/checksums +20 -0
- data/.yardoc/complete +0 -0
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +0 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +1 -1
- data/Gemfile.lock +30 -10
- data/README.md +1 -1
- data/Rakefile +8 -1
- data/bin/doing +76 -30
- data/doc/Array.html +135 -0
- data/doc/Doing/Color.html +506 -0
- data/doc/Doing/Configuration.html +680 -0
- data/doc/Doing/Errors/DoingNoTraceError.html +186 -0
- data/doc/Doing/Errors/DoingRuntimeError.html +186 -0
- data/doc/Doing/Errors/DoingStandardError.html +186 -0
- data/doc/Doing/Errors/EmptyInput.html +186 -0
- data/doc/Doing/Errors/NoResults.html +186 -0
- data/doc/Doing/Errors/PluginException.html +248 -0
- data/doc/Doing/Errors/UserCancelled.html +186 -0
- data/doc/Doing/Errors/WrongCommand.html +186 -0
- data/doc/Doing/Errors.html +191 -0
- data/doc/Doing/Hooks.html +364 -0
- data/doc/Doing/Item.html +1385 -0
- data/doc/Doing/Items.html +393 -0
- data/doc/Doing/LogAdapter.html +1650 -0
- data/doc/Doing/Note.html +535 -0
- data/doc/Doing/Pager.html +268 -0
- data/doc/Doing/Plugins.html +849 -0
- data/doc/Doing/Util.html +870 -0
- data/doc/Doing/WWID.html +4827 -0
- data/doc/Doing.html +145 -0
- data/doc/GLI/Commands/MarkdownDocumentListener.html +763 -0
- data/doc/GLI/Commands.html +115 -0
- data/doc/GLI.html +115 -0
- data/doc/Hash.html +332 -0
- data/doc/Status.html +292 -0
- data/doc/String.html +1714 -0
- data/doc/Symbol.html +250 -0
- data/doc/Time.html +182 -0
- data/doc/_index.html +411 -0
- data/doc/class_list.html +51 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +58 -0
- data/doc/css/style.css +497 -0
- data/doc/file.README.html +123 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +17 -0
- data/doc/index.html +123 -0
- data/doc/js/app.js +314 -0
- data/doc/js/full_list.js +216 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +1867 -0
- data/doc/top-level-namespace.html +112 -0
- data/doing.gemspec +5 -1
- data/doing.rdoc +86 -16
- data/example_plugin.rb +6 -6
- data/lib/doing/array.rb +1 -1
- data/lib/doing/configuration.rb +14 -12
- data/lib/doing/hash.rb +1 -1
- data/lib/doing/item.rb +101 -17
- data/lib/doing/log_adapter.rb +123 -113
- data/lib/doing/note.rb +1 -1
- data/lib/doing/plugin_manager.rb +5 -5
- data/lib/doing/plugins/export/csv_export.rb +1 -1
- data/lib/doing/plugins/export/template_export.rb +5 -7
- data/lib/doing/plugins/import/calendar_import.rb +1 -1
- data/lib/doing/plugins/import/doing_import.rb +4 -4
- data/lib/doing/plugins/import/timing_import.rb +5 -3
- data/lib/doing/string.rb +75 -22
- data/lib/doing/symbol.rb +9 -5
- data/lib/doing/time.rb +1 -1
- data/lib/doing/util.rb +18 -11
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +419 -326
- data/lib/doing/wwidfile.rb +5 -5
- data/lib/doing.rb +2 -1
- data/lib/examples/plugins/say_export.rb +6 -6
- data/rdocfixer.rb +1 -1
- data/yard_templates/default/method_details/setup.rb +3 -0
- metadata +117 -4
data/lib/doing/item.rb
CHANGED
@@ -2,11 +2,24 @@
|
|
2
2
|
|
3
3
|
module Doing
|
4
4
|
##
|
5
|
-
##
|
5
|
+
## This class describes a single WWID item
|
6
6
|
##
|
7
7
|
class Item
|
8
|
+
include Amatch
|
9
|
+
|
8
10
|
attr_accessor :date, :title, :section, :note
|
9
11
|
|
12
|
+
##
|
13
|
+
## Initialize an item with date, title, section, and
|
14
|
+
## optional note
|
15
|
+
##
|
16
|
+
## @param date [Time] The item's start date
|
17
|
+
## @param title [String] The title
|
18
|
+
## @param section [String] The section to which
|
19
|
+
## the item belongs
|
20
|
+
## @param note [Array or String] The note
|
21
|
+
## (optional)
|
22
|
+
##
|
10
23
|
def initialize(date, title, section, note = nil)
|
11
24
|
@date = date.is_a?(Time) ? date : Time.parse(date)
|
12
25
|
@title = title
|
@@ -18,14 +31,36 @@ module Doing
|
|
18
31
|
# @date = new_date.is_a?(Time) ? new_date : Time.parse(new_date)
|
19
32
|
# end
|
20
33
|
|
34
|
+
##
|
35
|
+
## Get the difference between the item's start date and
|
36
|
+
## the value of its @done tag (if present)
|
37
|
+
##
|
38
|
+
## @return Interval in seconds
|
39
|
+
##
|
21
40
|
def interval
|
22
41
|
@interval ||= calc_interval
|
23
42
|
end
|
24
43
|
|
44
|
+
##
|
45
|
+
## Get the value of the item's @done tag
|
46
|
+
##
|
47
|
+
## @return [Time] @done value
|
48
|
+
##
|
25
49
|
def end_date
|
26
50
|
@end_date ||= Time.parse(Regexp.last_match(1)) if @title =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/
|
27
51
|
end
|
28
52
|
|
53
|
+
def hash_id
|
54
|
+
(@date.to_s + @title + @section + @note.join(' ')).hash
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
## Test for equality between items
|
59
|
+
##
|
60
|
+
## @param other [Item] The other item
|
61
|
+
##
|
62
|
+
## @return [Boolean] is equal?
|
63
|
+
##
|
29
64
|
def equal?(other)
|
30
65
|
return false if @title.strip != other.title.strip
|
31
66
|
|
@@ -36,10 +71,25 @@ module Doing
|
|
36
71
|
true
|
37
72
|
end
|
38
73
|
|
74
|
+
##
|
75
|
+
## Test if two items occur at the same time (same start date and equal duration)
|
76
|
+
##
|
77
|
+
## @param item_b [Item] The item to compare
|
78
|
+
##
|
79
|
+
## @return [Boolean] is equal?
|
80
|
+
##
|
39
81
|
def same_time?(item_b)
|
40
82
|
date == item_b.date ? interval == item_b.interval : false
|
41
83
|
end
|
42
84
|
|
85
|
+
##
|
86
|
+
## Test if the interval between start date and @done
|
87
|
+
## value overlaps with another item's
|
88
|
+
##
|
89
|
+
## @param item_b [Item] The item to compare
|
90
|
+
##
|
91
|
+
## @return [Boolean] overlaps?
|
92
|
+
##
|
43
93
|
def overlapping_time?(item_b)
|
44
94
|
return true if same_time?(item_b)
|
45
95
|
|
@@ -52,14 +102,37 @@ module Doing
|
|
52
102
|
(start_a >= start_b && start_a <= end_b) || (end_a >= start_b && end_a <= end_b) || (start_a < start_b && end_a > end_b)
|
53
103
|
end
|
54
104
|
|
105
|
+
##
|
106
|
+
## Add (or remove) tags from the title of the item
|
107
|
+
##
|
108
|
+
## @param tag [String] The tag to add
|
109
|
+
## @param value [String] A value to include as @tag(value)
|
110
|
+
## @param remove [Boolean] if true remove instead of adding
|
111
|
+
## @param rename_to [String] if not nil, rename target tag to this tag name
|
112
|
+
## @param regex [Boolean] treat target tag string as regex pattern
|
113
|
+
##
|
55
114
|
def tag(tag, value: nil, remove: false, rename_to: nil, regex: false)
|
56
115
|
@title.tag!(tag, value: value, remove: remove, rename_to: rename_to, regex: regex).strip!
|
57
116
|
end
|
58
117
|
|
118
|
+
##
|
119
|
+
## Get a list of tags on the item
|
120
|
+
##
|
121
|
+
## @return [Array] array of tags (no values)
|
122
|
+
##
|
59
123
|
def tags
|
60
124
|
@title.scan(/(?<= |\A)@([^\s(]+)/).map {|tag| tag[0]}.sort.uniq
|
61
125
|
end
|
62
126
|
|
127
|
+
##
|
128
|
+
## Test if item contains tag(s)
|
129
|
+
##
|
130
|
+
## @param tags (Array or String) The tags to test. Can be an array or a comma-separated string.
|
131
|
+
## @param bool (Symbol) The boolean to use for multiple tags (:and, :or, :not)
|
132
|
+
## @param negate [Boolean] negate the result?
|
133
|
+
##
|
134
|
+
## @return [Boolean] true if tag/bool combination passes
|
135
|
+
##
|
63
136
|
def tags?(tags, bool = :and, negate: false)
|
64
137
|
tags = split_tags(tags)
|
65
138
|
bool = bool.normalize_bool
|
@@ -75,26 +148,37 @@ module Doing
|
|
75
148
|
negate ? !matches : matches
|
76
149
|
end
|
77
150
|
|
78
|
-
|
151
|
+
##
|
152
|
+
## Test if item matches search string
|
153
|
+
##
|
154
|
+
## @param search [String] The search string
|
155
|
+
## @param negate [Boolean] negate results
|
156
|
+
## @param case_type (Symbol) The case-sensitivity
|
157
|
+
## type (:sensitive,
|
158
|
+
## :ignore, :smart)
|
159
|
+
##
|
160
|
+
## @return [Boolean] matches search criteria
|
161
|
+
##
|
162
|
+
def search(search, distance: 3, negate: false, case_type: :smart, fuzzy: false)
|
79
163
|
text = @title + @note.to_s
|
80
|
-
pattern = case search.strip
|
81
|
-
when %r{^/.*?/$}
|
82
|
-
search.sub(%r{/(.*?)/}, '\1')
|
83
|
-
when /^'/
|
84
|
-
case_sensitive = true
|
85
|
-
search.sub(/^'(.*?)'?$/, '\1')
|
86
|
-
else
|
87
|
-
if case_type == :smart
|
88
|
-
case_sensitive = true if search =~ /[A-Z]/
|
89
|
-
else
|
90
|
-
case_sensitive = case_type == :sensitive
|
91
|
-
end
|
92
164
|
|
93
|
-
|
165
|
+
if search.is_rx? || !fuzzy
|
166
|
+
matches = text =~ search.to_rx(distance: distance, case_type: case_type)
|
167
|
+
else
|
168
|
+
distance = 0.25 if distance > 1
|
169
|
+
score = if (case_type == :smart && search !~ /[A-Z]/) || case_type == :ignore
|
170
|
+
text.downcase.pair_distance_similar(search.downcase)
|
171
|
+
else
|
172
|
+
score = text.pair_distance_similar(search)
|
94
173
|
end
|
95
|
-
rx = Regexp.new(pattern, !case_sensitive)
|
96
174
|
|
97
|
-
|
175
|
+
if score >= distance
|
176
|
+
matches = true
|
177
|
+
Doing.logger.debug('Fuzzy Match:', %(#{@title}, "#{search}" #{score}))
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
negate ? !matches : matches
|
98
182
|
end
|
99
183
|
|
100
184
|
def should_finish?
|
data/lib/doing/log_adapter.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Doing
|
4
4
|
##
|
5
|
-
##
|
5
|
+
## Log adapter
|
6
6
|
##
|
7
7
|
class LogAdapter
|
8
8
|
attr_writer :logdev, :max_length
|
@@ -32,7 +32,7 @@ module Doing
|
|
32
32
|
].freeze
|
33
33
|
|
34
34
|
#
|
35
|
-
#
|
35
|
+
# Create a new instance of a log writer
|
36
36
|
#
|
37
37
|
# @param level (optional, symbol) the log level
|
38
38
|
#
|
@@ -47,29 +47,25 @@ module Doing
|
|
47
47
|
end
|
48
48
|
|
49
49
|
#
|
50
|
-
#
|
50
|
+
# Set the log level on the writer
|
51
51
|
#
|
52
52
|
# @param level (symbol) the log level
|
53
53
|
#
|
54
54
|
# @return nothing
|
55
55
|
#
|
56
|
-
def log_level=(level)
|
57
|
-
level ||= 'info'
|
56
|
+
def log_level=(level = 'info')
|
58
57
|
level = level.to_s
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
else
|
71
|
-
level = level.downcase.to_sym
|
72
|
-
end
|
58
|
+
|
59
|
+
level = case level
|
60
|
+
when /^[e0]/i
|
61
|
+
:error
|
62
|
+
when /^[w1]/i
|
63
|
+
:warn
|
64
|
+
when /^[d3]/i
|
65
|
+
:debug
|
66
|
+
else
|
67
|
+
:info
|
68
|
+
end
|
73
69
|
|
74
70
|
@level = level
|
75
71
|
end
|
@@ -84,46 +80,6 @@ module Doing
|
|
84
80
|
# log_now :debug, 'Doing Version:', Doing::VERSION
|
85
81
|
end
|
86
82
|
|
87
|
-
def format_counter(key, data)
|
88
|
-
case key
|
89
|
-
when :added_tags
|
90
|
-
['Tagged:', data[:message] || 'added %tags to %count %items']
|
91
|
-
when :removed_tags
|
92
|
-
['Untagged:', data[:message] || 'removed %tags from %count %items']
|
93
|
-
when :added
|
94
|
-
['Added:', data[:message] || 'added %count new %items']
|
95
|
-
when :updated
|
96
|
-
['Updated:', data[:message] || 'updated %count %items']
|
97
|
-
when :deleted
|
98
|
-
['Deleted:', data[:message] || 'deleted %count %items']
|
99
|
-
when :moved
|
100
|
-
['Moved:', data[:message] || 'moved %count %items']
|
101
|
-
when :completed
|
102
|
-
['Completed:', data[:message] || 'completed %count %items']
|
103
|
-
when :archived
|
104
|
-
['Archived:', data[:message] || 'archived %count %items']
|
105
|
-
when :completed_archived
|
106
|
-
['Archived:', data[:message] || 'completed and archived %count %items']
|
107
|
-
when :skipped
|
108
|
-
['Skipped:', data[:message] || '%count %items were unchanged']
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def total_counters
|
113
|
-
@counters.each do |key, data|
|
114
|
-
next if data[:count].zero?
|
115
|
-
|
116
|
-
count = data[:count]
|
117
|
-
tags = data[:tag] ? data[:tag].uniq.map { |t| "@#{t}".cyan }.join(', ') : 'tags'
|
118
|
-
topic, m = format_counter(key, data)
|
119
|
-
message = m.dup
|
120
|
-
message.sub!(/%count/, count.to_s)
|
121
|
-
message.sub!(/%items/, count == 1 ? 'item' : 'items')
|
122
|
-
message.sub!(/%tags/, tags)
|
123
|
-
write(data[:level], topic, message)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
83
|
def count(key, level: :info, count: 1, tag: nil, message: nil)
|
128
84
|
raise ArgumentError, 'invalid counter key' unless COUNT_KEYS.include?(key)
|
129
85
|
|
@@ -134,7 +90,7 @@ module Doing
|
|
134
90
|
end
|
135
91
|
|
136
92
|
#
|
137
|
-
#
|
93
|
+
# Print a debug message
|
138
94
|
#
|
139
95
|
# @param topic the topic of the message
|
140
96
|
# @param message the message detail
|
@@ -146,7 +102,7 @@ module Doing
|
|
146
102
|
end
|
147
103
|
|
148
104
|
#
|
149
|
-
#
|
105
|
+
# Print a message
|
150
106
|
#
|
151
107
|
# @param topic the topic of the message, e.g.
|
152
108
|
# "Configuration file",
|
@@ -160,7 +116,7 @@ module Doing
|
|
160
116
|
end
|
161
117
|
|
162
118
|
#
|
163
|
-
#
|
119
|
+
# Print a message
|
164
120
|
#
|
165
121
|
# @param topic the topic of the message, e.g.
|
166
122
|
# "Configuration file",
|
@@ -174,7 +130,7 @@ module Doing
|
|
174
130
|
end
|
175
131
|
|
176
132
|
#
|
177
|
-
#
|
133
|
+
# Print an error message
|
178
134
|
#
|
179
135
|
# @param topic the topic of the message, e.g.
|
180
136
|
# "Configuration file",
|
@@ -188,7 +144,7 @@ module Doing
|
|
188
144
|
end
|
189
145
|
|
190
146
|
#
|
191
|
-
#
|
147
|
+
# Print an error message and immediately
|
192
148
|
# abort the process
|
193
149
|
#
|
194
150
|
# @param topic the topic of the message, e.g.
|
@@ -204,33 +160,8 @@ module Doing
|
|
204
160
|
abort
|
205
161
|
end
|
206
162
|
|
207
|
-
# Internal: Build a topic method
|
208
163
|
#
|
209
|
-
#
|
210
|
-
# "Configuration file",
|
211
|
-
# "Deprecation", etc.
|
212
|
-
# @param message the message detail
|
213
|
-
#
|
214
|
-
# @return the formatted message
|
215
|
-
#
|
216
|
-
def message(topic, message = nil)
|
217
|
-
raise ArgumentError, 'block or message, not both' if block_given? && message
|
218
|
-
|
219
|
-
message = yield if block_given?
|
220
|
-
message = message.to_s.gsub(/\s+/, ' ')
|
221
|
-
|
222
|
-
return topic.ljust(TOPIC_WIDTH) if topic && message.strip.empty?
|
223
|
-
|
224
|
-
topic = formatted_topic(topic, colon: block_given?)
|
225
|
-
message.truncmiddle!(@max_length - TOPIC_WIDTH - 5)
|
226
|
-
out = topic + message
|
227
|
-
out.truncate!(@max_length) if @max_length.positive?
|
228
|
-
messages << out
|
229
|
-
out
|
230
|
-
end
|
231
|
-
|
232
|
-
#
|
233
|
-
# @brief Format the topic
|
164
|
+
# Format the topic
|
234
165
|
#
|
235
166
|
# @param topic the topic of the message, e.g.
|
236
167
|
# "Configuration file",
|
@@ -250,39 +181,34 @@ module Doing
|
|
250
181
|
end
|
251
182
|
|
252
183
|
#
|
253
|
-
#
|
254
|
-
# given the log level.
|
255
|
-
#
|
256
|
-
# @param level_of_message the Symbol level of
|
257
|
-
# message, one of :debug,
|
258
|
-
# :info, :warn, :error
|
259
|
-
#
|
260
|
-
# @return whether the message should be written.
|
261
|
-
#
|
262
|
-
def write_message?(level_of_message)
|
263
|
-
LOG_LEVELS.fetch(@level) <= LOG_LEVELS.fetch(level_of_message)
|
264
|
-
end
|
265
|
-
|
266
|
-
#
|
267
|
-
# @brief Log a message.
|
184
|
+
# Log a message.
|
268
185
|
#
|
269
|
-
# @param level_of_message the Symbol
|
270
|
-
# message, one of
|
271
|
-
# :info, :warn,
|
272
|
-
#
|
273
|
-
#
|
274
|
-
#
|
275
|
-
#
|
186
|
+
# @param level_of_message [Symbol] the Symbol
|
187
|
+
# level of message, one of
|
188
|
+
# :debug, :info, :warn,
|
189
|
+
# :error
|
190
|
+
# @param topic [String] the String
|
191
|
+
# topic or full message
|
192
|
+
# @param message [String] the String
|
193
|
+
# message (optional)
|
276
194
|
# @param block a block containing the
|
277
195
|
# message (optional)
|
278
196
|
#
|
279
|
-
# @return false if the message was not written
|
197
|
+
# @return [Boolean] false if the message was not written
|
280
198
|
#
|
281
199
|
def write(level_of_message, topic, message = nil, &block)
|
282
200
|
@results << { level: level_of_message, message: message(topic, message, &block) }
|
283
201
|
true
|
284
202
|
end
|
285
203
|
|
204
|
+
##
|
205
|
+
## Log to console immediately instead of writing messages on exit
|
206
|
+
##
|
207
|
+
## @param level [Symbol] The level
|
208
|
+
## @param topic [String] The topic or full message
|
209
|
+
## @param message [String] The message (optional)
|
210
|
+
## @param block a block containing the message (optional)
|
211
|
+
##
|
286
212
|
def log_now(level, topic, message = nil, &block)
|
287
213
|
return false unless write_message?(level)
|
288
214
|
|
@@ -293,6 +219,11 @@ module Doing
|
|
293
219
|
end
|
294
220
|
end
|
295
221
|
|
222
|
+
##
|
223
|
+
## Output registers based on log level
|
224
|
+
##
|
225
|
+
## @return nothing
|
226
|
+
##
|
296
227
|
def output_results
|
297
228
|
total_counters
|
298
229
|
|
@@ -309,6 +240,85 @@ module Doing
|
|
309
240
|
|
310
241
|
private
|
311
242
|
|
243
|
+
def format_counter(key, data)
|
244
|
+
case key
|
245
|
+
when :added_tags
|
246
|
+
['Tagged:', data[:message] || 'added %tags to %count %items']
|
247
|
+
when :removed_tags
|
248
|
+
['Untagged:', data[:message] || 'removed %tags from %count %items']
|
249
|
+
when :added
|
250
|
+
['Added:', data[:message] || 'added %count new %items']
|
251
|
+
when :updated
|
252
|
+
['Updated:', data[:message] || 'updated %count %items']
|
253
|
+
when :deleted
|
254
|
+
['Deleted:', data[:message] || 'deleted %count %items']
|
255
|
+
when :moved
|
256
|
+
['Moved:', data[:message] || 'moved %count %items']
|
257
|
+
when :completed
|
258
|
+
['Completed:', data[:message] || 'completed %count %items']
|
259
|
+
when :archived
|
260
|
+
['Archived:', data[:message] || 'archived %count %items']
|
261
|
+
when :completed_archived
|
262
|
+
['Archived:', data[:message] || 'completed and archived %count %items']
|
263
|
+
when :skipped
|
264
|
+
['Skipped:', data[:message] || '%count %items were unchanged']
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def total_counters
|
269
|
+
@counters.each do |key, data|
|
270
|
+
next if data[:count].zero?
|
271
|
+
|
272
|
+
count = data[:count]
|
273
|
+
tags = data[:tag] ? data[:tag].uniq.map { |t| "@#{t}".cyan }.join(', ') : 'tags'
|
274
|
+
topic, m = format_counter(key, data)
|
275
|
+
message = m.dup
|
276
|
+
message.sub!(/%count/, count.to_s)
|
277
|
+
message.sub!(/%items/, count == 1 ? 'item' : 'items')
|
278
|
+
message.sub!(/%tags/, tags)
|
279
|
+
write(data[:level], topic, message)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
#
|
284
|
+
# Check if the message should be written
|
285
|
+
# given the log level.
|
286
|
+
#
|
287
|
+
# @param level_of_message the Symbol level of
|
288
|
+
# message, one of :debug,
|
289
|
+
# :info, :warn, :error
|
290
|
+
#
|
291
|
+
# @return whether the message should be written.
|
292
|
+
#
|
293
|
+
def write_message?(level_of_message)
|
294
|
+
LOG_LEVELS.fetch(@level) <= LOG_LEVELS.fetch(level_of_message)
|
295
|
+
end
|
296
|
+
|
297
|
+
# Internal: Build a topic method
|
298
|
+
#
|
299
|
+
# @param topic the topic of the message, e.g.
|
300
|
+
# "Configuration file",
|
301
|
+
# "Deprecation", etc.
|
302
|
+
# @param message the message detail
|
303
|
+
#
|
304
|
+
# @return the formatted message
|
305
|
+
#
|
306
|
+
def message(topic, message = nil)
|
307
|
+
raise ArgumentError, 'block or message, not both' if block_given? && message
|
308
|
+
|
309
|
+
message = yield if block_given?
|
310
|
+
message = message.to_s.gsub(/\s+/, ' ')
|
311
|
+
|
312
|
+
return topic.ljust(TOPIC_WIDTH) if topic && message.strip.empty?
|
313
|
+
|
314
|
+
topic = formatted_topic(topic, colon: block_given?)
|
315
|
+
message.truncmiddle!(@max_length - TOPIC_WIDTH - 5)
|
316
|
+
out = topic + message
|
317
|
+
out.truncate!(@max_length) if @max_length.positive?
|
318
|
+
messages << out
|
319
|
+
out
|
320
|
+
end
|
321
|
+
|
312
322
|
def color_message(level, topic, message = nil, &block)
|
313
323
|
colors = Doing::Color
|
314
324
|
message = message(topic, message, &block)
|
data/lib/doing/note.rb
CHANGED
data/lib/doing/plugin_manager.rb
CHANGED
@@ -107,7 +107,7 @@ module Doing
|
|
107
107
|
end
|
108
108
|
|
109
109
|
##
|
110
|
-
##
|
110
|
+
## List available plugins to stdout
|
111
111
|
##
|
112
112
|
## @param options { type, separator }
|
113
113
|
##
|
@@ -129,11 +129,11 @@ module Doing
|
|
129
129
|
end
|
130
130
|
|
131
131
|
##
|
132
|
-
##
|
132
|
+
## Return array of available plugin names
|
133
133
|
##
|
134
134
|
## @param type Plugin type (:import, :export)
|
135
135
|
##
|
136
|
-
## @
|
136
|
+
## @return [Array<String>] plugin names
|
137
137
|
##
|
138
138
|
def available_plugins(type: :export)
|
139
139
|
type = valid_type(type)
|
@@ -141,7 +141,7 @@ module Doing
|
|
141
141
|
end
|
142
142
|
|
143
143
|
##
|
144
|
-
##
|
144
|
+
## Return string version of plugin names
|
145
145
|
##
|
146
146
|
## @param type Plugin type (:import, :export)
|
147
147
|
## @param separator The separator to join names with
|
@@ -154,7 +154,7 @@ module Doing
|
|
154
154
|
end
|
155
155
|
|
156
156
|
##
|
157
|
-
##
|
157
|
+
## Return a regular expression of all
|
158
158
|
## plugin triggers for type
|
159
159
|
##
|
160
160
|
## @param type The type :import or :export
|
@@ -94,7 +94,7 @@ module Doing
|
|
94
94
|
end
|
95
95
|
|
96
96
|
if note.empty?
|
97
|
-
output.gsub!(/%([io]d|(\^.)?(([ _t]|[^a-z0-9])?\d+)?(.[ _t]?)?)?note/, '')
|
97
|
+
output.gsub!(/%(chomp|[io]d|(\^.)?(([ _t]|[^a-z0-9])?\d+)?(.[ _t]?)?)?note/, '')
|
98
98
|
else
|
99
99
|
output.sub!(/%note/, "\n#{note.map { |l| "\t#{l.strip} " }.join("\n")}")
|
100
100
|
output.sub!(/%idnote/, "\n#{note.map { |l| "\t\t#{l.strip} " }.join("\n")}")
|
@@ -111,15 +111,13 @@ module Doing
|
|
111
111
|
prefix = m['prefix'] || ''
|
112
112
|
"\n#{note.map { |l| "#{mark}#{indent}#{prefix}#{l.strip} " }.join("\n")}"
|
113
113
|
end
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
end
|
118
|
-
chomp_note.join(' ')
|
114
|
+
|
115
|
+
output.sub!(/%chompnote/) do
|
116
|
+
note.map { |l| l.gsub(/\n+/, ' ').gsub(/(^\s*|\s*$)/, '').gsub(/\s+/, ' ') }.join(' ')
|
119
117
|
end
|
120
118
|
end
|
121
119
|
|
122
|
-
output.gsub!(/%hr(_under)?/) do
|
120
|
+
output.gsub!(/%hr(_under)?/) do
|
123
121
|
o = ''
|
124
122
|
`tput cols`.to_i.times do
|
125
123
|
o += Regexp.last_match(1).nil? ? '-' : '_'
|
@@ -15,11 +15,11 @@ module Doing
|
|
15
15
|
end
|
16
16
|
|
17
17
|
##
|
18
|
-
##
|
18
|
+
## Imports a Doing file
|
19
19
|
##
|
20
|
-
## @param wwid WWID object
|
21
|
-
## @param path
|
22
|
-
## @param options
|
20
|
+
## @param wwid [WWID] WWID object
|
21
|
+
## @param path [String] Path to Doing file
|
22
|
+
## @param options [Hash] Additional Options
|
23
23
|
##
|
24
24
|
## @return Nothing
|
25
25
|
##
|
@@ -15,10 +15,12 @@ module Doing
|
|
15
15
|
end
|
16
16
|
|
17
17
|
##
|
18
|
-
##
|
18
|
+
## Imports a Timing report
|
19
19
|
##
|
20
|
-
## @param
|
21
|
-
## @param
|
20
|
+
## @param wwid [WWID] The wwid object
|
21
|
+
## @param path [String] Path to JSON report
|
22
|
+
## file
|
23
|
+
## @param options [Hash] Additional Options
|
22
24
|
##
|
23
25
|
def self.import(wwid, path, options: {})
|
24
26
|
exit_now! 'Path to JSON report required' if path.nil?
|