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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.yardoc/checksums +20 -0
  3. data/.yardoc/complete +0 -0
  4. data/.yardoc/object_types +0 -0
  5. data/.yardoc/objects/root.dat +0 -0
  6. data/.yardoc/proxy_types +0 -0
  7. data/.yardopts +1 -0
  8. data/CHANGELOG.md +1 -1
  9. data/Gemfile.lock +30 -10
  10. data/README.md +1 -1
  11. data/Rakefile +8 -1
  12. data/bin/doing +76 -30
  13. data/doc/Array.html +135 -0
  14. data/doc/Doing/Color.html +506 -0
  15. data/doc/Doing/Configuration.html +680 -0
  16. data/doc/Doing/Errors/DoingNoTraceError.html +186 -0
  17. data/doc/Doing/Errors/DoingRuntimeError.html +186 -0
  18. data/doc/Doing/Errors/DoingStandardError.html +186 -0
  19. data/doc/Doing/Errors/EmptyInput.html +186 -0
  20. data/doc/Doing/Errors/NoResults.html +186 -0
  21. data/doc/Doing/Errors/PluginException.html +248 -0
  22. data/doc/Doing/Errors/UserCancelled.html +186 -0
  23. data/doc/Doing/Errors/WrongCommand.html +186 -0
  24. data/doc/Doing/Errors.html +191 -0
  25. data/doc/Doing/Hooks.html +364 -0
  26. data/doc/Doing/Item.html +1385 -0
  27. data/doc/Doing/Items.html +393 -0
  28. data/doc/Doing/LogAdapter.html +1650 -0
  29. data/doc/Doing/Note.html +535 -0
  30. data/doc/Doing/Pager.html +268 -0
  31. data/doc/Doing/Plugins.html +849 -0
  32. data/doc/Doing/Util.html +870 -0
  33. data/doc/Doing/WWID.html +4827 -0
  34. data/doc/Doing.html +145 -0
  35. data/doc/GLI/Commands/MarkdownDocumentListener.html +763 -0
  36. data/doc/GLI/Commands.html +115 -0
  37. data/doc/GLI.html +115 -0
  38. data/doc/Hash.html +332 -0
  39. data/doc/Status.html +292 -0
  40. data/doc/String.html +1714 -0
  41. data/doc/Symbol.html +250 -0
  42. data/doc/Time.html +182 -0
  43. data/doc/_index.html +411 -0
  44. data/doc/class_list.html +51 -0
  45. data/doc/css/common.css +1 -0
  46. data/doc/css/full_list.css +58 -0
  47. data/doc/css/style.css +497 -0
  48. data/doc/file.README.html +123 -0
  49. data/doc/file_list.html +56 -0
  50. data/doc/frames.html +17 -0
  51. data/doc/index.html +123 -0
  52. data/doc/js/app.js +314 -0
  53. data/doc/js/full_list.js +216 -0
  54. data/doc/js/jquery.js +4 -0
  55. data/doc/method_list.html +1867 -0
  56. data/doc/top-level-namespace.html +112 -0
  57. data/doing.gemspec +5 -1
  58. data/doing.rdoc +86 -16
  59. data/example_plugin.rb +6 -6
  60. data/lib/doing/array.rb +1 -1
  61. data/lib/doing/configuration.rb +14 -12
  62. data/lib/doing/hash.rb +1 -1
  63. data/lib/doing/item.rb +101 -17
  64. data/lib/doing/log_adapter.rb +123 -113
  65. data/lib/doing/note.rb +1 -1
  66. data/lib/doing/plugin_manager.rb +5 -5
  67. data/lib/doing/plugins/export/csv_export.rb +1 -1
  68. data/lib/doing/plugins/export/template_export.rb +5 -7
  69. data/lib/doing/plugins/import/calendar_import.rb +1 -1
  70. data/lib/doing/plugins/import/doing_import.rb +4 -4
  71. data/lib/doing/plugins/import/timing_import.rb +5 -3
  72. data/lib/doing/string.rb +75 -22
  73. data/lib/doing/symbol.rb +9 -5
  74. data/lib/doing/time.rb +1 -1
  75. data/lib/doing/util.rb +18 -11
  76. data/lib/doing/version.rb +1 -1
  77. data/lib/doing/wwid.rb +419 -326
  78. data/lib/doing/wwidfile.rb +5 -5
  79. data/lib/doing.rb +2 -1
  80. data/lib/examples/plugins/say_export.rb +6 -6
  81. data/rdocfixer.rb +1 -1
  82. data/yard_templates/default/method_details/setup.rb +3 -0
  83. metadata +117 -4
data/lib/doing/item.rb CHANGED
@@ -2,11 +2,24 @@
2
2
 
3
3
  module Doing
4
4
  ##
5
- ## @brief This class describes a single WWID item
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
- def search(search, negate: false, case_type: :smart)
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
- search.split('').join('.{0,3}')
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
- negate ? text !~ rx : text =~ rx
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?
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Doing
4
4
  ##
5
- ## @brief Log adapter
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
- # @brief Create a new instance of a log writer
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
- # @brief Set the log level on the writer
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
- if level.is_a?(String) && level =~ /^([ewid]\w+|[0123])$/
60
- level = case level
61
- when /^[e0]/
62
- :error
63
- when /^[w1]/
64
- :warn
65
- when /^[i2]/
66
- :info
67
- when /^[d3]/
68
- :debug
69
- end
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
- # @brief Print a debug message
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
- # @brief Print a message
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
- # @brief Print a message
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
- # @brief Print an error message
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
- # @brief Print an error message and immediately
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
- # @param topic the topic of the message, e.g.
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
- # @brief Check if the message should be written
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 level of
270
- # message, one of :debug,
271
- # :info, :warn, :error
272
- # @param topic the String topic or full
273
- # message
274
- # @param message the String message
275
- # (optional)
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
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Doing
4
4
  ##
5
- ## @brief This class describes an item note.
5
+ ## This class describes an item note.
6
6
  ##
7
7
  class Note < Array
8
8
  def initialize(note = [])
@@ -107,7 +107,7 @@ module Doing
107
107
  end
108
108
 
109
109
  ##
110
- ## @brief List available plugins to stdout
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
- ## @brief Return array of available plugin names
132
+ ## Return array of available plugin names
133
133
  ##
134
134
  ## @param type Plugin type (:import, :export)
135
135
  ##
136
- ## @returns [Array<String>] plugin names
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
- ## @brief Return string version of plugin names
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
- ## @brief Return a regular expression of all
157
+ ## Return a regular expression of all
158
158
  ## plugin triggers for type
159
159
  ##
160
160
  ## @param type The type :import or :export
@@ -6,7 +6,7 @@
6
6
  # url: https://brettterpstra.com
7
7
  module Doing
8
8
  ##
9
- ## @brief CSV Export
9
+ ## CSV Export
10
10
  ##
11
11
  class CSVExport
12
12
  include Doing::Util
@@ -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
- output.sub!(/%chompnote/) do |_m|
115
- chomp_note = note.map do |l|
116
- l.gsub(/\n+/, ' ').gsub(/(^\s*|\s*$)/, '').gsub(/\s+/, ' ')
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 |_m|
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? ? '-' : '_'
@@ -8,7 +8,7 @@ require 'json'
8
8
 
9
9
  module Doing
10
10
  ##
11
- ## @brief Plugin for importing from Calendar.app on macOS
11
+ ## Plugin for importing from Calendar.app on macOS
12
12
  ##
13
13
  class CalendarImport
14
14
  include Doing::Util
@@ -15,11 +15,11 @@ module Doing
15
15
  end
16
16
 
17
17
  ##
18
- ## @brief Imports a Doing file
18
+ ## Imports a Doing file
19
19
  ##
20
- ## @param wwid WWID object
21
- ## @param path (String) Path to Doing file
22
- ## @param options (Hash) Additional 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
- ## @brief Imports a Timing report
18
+ ## Imports a Timing report
19
19
  ##
20
- ## @param path (String) Path to JSON report file
21
- ## @param options (Hash) Additional Options
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?