doing 2.0.9.pre → 2.0.10
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/.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?
|