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.
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?