doing 2.1.89 → 2.1.90

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 (242) hide show
  1. checksums.yaml +4 -4
  2. data/.irbrc +2 -0
  3. data/.rubocop.yml +1 -0
  4. data/.rubocop_todo.yml +251 -0
  5. data/CHANGELOG.md +22 -0
  6. data/Gemfile +2 -0
  7. data/Gemfile.lock +1 -1
  8. data/Rakefile +5 -3
  9. data/bin/commands/changes.rb +3 -1
  10. data/bin/commands/choose.rb +2 -0
  11. data/bin/commands/colors.rb +5 -3
  12. data/bin/commands/commands_accepting.rb +3 -3
  13. data/bin/commands/completion.rb +2 -1
  14. data/bin/commands/config.rb +8 -6
  15. data/bin/commands/done.rb +19 -12
  16. data/bin/commands/finish.rb +4 -2
  17. data/bin/commands/grep.rb +9 -5
  18. data/bin/commands/import.rb +14 -11
  19. data/bin/commands/install_fzf.rb +4 -2
  20. data/bin/commands/last.rb +31 -27
  21. data/bin/commands/meanwhile.rb +6 -2
  22. data/bin/commands/note.rb +6 -3
  23. data/bin/commands/now.rb +2 -0
  24. data/bin/commands/open.rb +6 -1
  25. data/bin/commands/plugins.rb +2 -0
  26. data/bin/commands/recent.rb +47 -33
  27. data/bin/commands/reset.rb +7 -3
  28. data/bin/commands/rotate.rb +6 -3
  29. data/bin/commands/sections.rb +3 -3
  30. data/bin/commands/select.rb +2 -0
  31. data/bin/commands/show.rb +24 -20
  32. data/bin/commands/since.rb +10 -3
  33. data/bin/commands/tag.rb +18 -16
  34. data/bin/commands/tag_dir.rb +5 -2
  35. data/bin/commands/tags.rb +17 -17
  36. data/bin/commands/template.rb +8 -2
  37. data/bin/commands/today.rb +10 -2
  38. data/bin/commands/undo.rb +2 -0
  39. data/bin/commands/update.rb +9 -7
  40. data/bin/commands/view.rb +11 -8
  41. data/bin/commands/views.rb +2 -0
  42. data/bin/commands/yesterday.rb +6 -1
  43. data/bin/doing +54 -57
  44. data/docs/doc/Array.html +3 -3
  45. data/docs/doc/BooleanTermParser/Clause.html +3 -3
  46. data/docs/doc/BooleanTermParser/Operator.html +3 -3
  47. data/docs/doc/BooleanTermParser/Query.html +3 -3
  48. data/docs/doc/BooleanTermParser/QueryParser.html +3 -3
  49. data/docs/doc/BooleanTermParser/QueryTransformer.html +3 -3
  50. data/docs/doc/BooleanTermParser.html +3 -3
  51. data/docs/doc/Doing/ArrayCleanup.html +3 -3
  52. data/docs/doc/Doing/ArrayNestedHash.html +3 -3
  53. data/docs/doc/Doing/ArrayTags.html +9 -9
  54. data/docs/doc/Doing/ByDayExport.html +3 -3
  55. data/docs/doc/Doing/CSVExport.html +4 -4
  56. data/docs/doc/Doing/CalendarImport.html +4 -4
  57. data/docs/doc/Doing/Change.html +3 -3
  58. data/docs/doc/Doing/Changes.html +3 -3
  59. data/docs/doc/Doing/ChronifyArray.html +3 -3
  60. data/docs/doc/Doing/ChronifyNumeric.html +3 -3
  61. data/docs/doc/Doing/ChronifyString.html +6 -6
  62. data/docs/doc/Doing/Color.html +88 -47
  63. data/docs/doc/Doing/Completion/BashCompletions.html +3 -3
  64. data/docs/doc/Doing/Completion/FigCompletions.html +3 -3
  65. data/docs/doc/Doing/Completion/FishCompletions.html +3 -3
  66. data/docs/doc/Doing/Completion/StringUtils.html +3 -3
  67. data/docs/doc/Doing/Completion/ZshCompletions.html +3 -3
  68. data/docs/doc/Doing/Completion.html +5 -5
  69. data/docs/doc/Doing/Configuration.html +6 -6
  70. data/docs/doc/Doing/DayOneRenderer.html +3 -3
  71. data/docs/doc/Doing/DayoneExport.html +4 -4
  72. data/docs/doc/Doing/DoingExport.html +5 -5
  73. data/docs/doc/Doing/DoingImport.html +4 -4
  74. data/docs/doc/Doing/Entry.html +3 -3
  75. data/docs/doc/Doing/Errors/DoingNoTraceError.html +3 -3
  76. data/docs/doc/Doing/Errors/DoingRuntimeError.html +3 -3
  77. data/docs/doc/Doing/Errors/DoingStandardError.html +3 -3
  78. data/docs/doc/Doing/Errors/EmptyInput.html +3 -3
  79. data/docs/doc/Doing/Errors/HistoryLimitError.html +3 -3
  80. data/docs/doc/Doing/Errors/InvalidPlugin.html +3 -3
  81. data/docs/doc/Doing/Errors/MissingBackupFile.html +3 -3
  82. data/docs/doc/Doing/Errors/NoResults.html +3 -3
  83. data/docs/doc/Doing/Errors/PluginException.html +3 -3
  84. data/docs/doc/Doing/Errors/UserCancelled.html +3 -3
  85. data/docs/doc/Doing/Errors/WrongCommand.html +3 -3
  86. data/docs/doc/Doing/Errors.html +3 -3
  87. data/docs/doc/Doing/HTMLExport.html +4 -4
  88. data/docs/doc/Doing/Hooks.html +3 -16
  89. data/docs/doc/Doing/Item.html +4 -4
  90. data/docs/doc/Doing/ItemDates.html +3 -3
  91. data/docs/doc/Doing/ItemQuery.html +3 -3
  92. data/docs/doc/Doing/ItemState.html +3 -3
  93. data/docs/doc/Doing/ItemTags.html +3 -3
  94. data/docs/doc/Doing/Items.html +3 -3
  95. data/docs/doc/Doing/JSONExport.html +4 -4
  96. data/docs/doc/Doing/JSONImport.html +4 -4
  97. data/docs/doc/Doing/Logger.html +183 -3
  98. data/docs/doc/Doing/MarkdownExport.html +4 -4
  99. data/docs/doc/Doing/Note.html +3 -3
  100. data/docs/doc/Doing/Pager.html +54 -58
  101. data/docs/doc/Doing/Plugins.html +3 -3
  102. data/docs/doc/Doing/Prompt.html +4 -4
  103. data/docs/doc/Doing/PromptChoose.html +3 -3
  104. data/docs/doc/Doing/PromptFZF.html +3 -3
  105. data/docs/doc/Doing/PromptInput.html +3 -3
  106. data/docs/doc/Doing/PromptSTD.html +3 -3
  107. data/docs/doc/Doing/PromptYN.html +3 -3
  108. data/docs/doc/Doing/Section.html +3 -3
  109. data/docs/doc/Doing/StringHighlight.html +3 -3
  110. data/docs/doc/Doing/StringNormalize.html +3 -3
  111. data/docs/doc/Doing/StringQuery.html +4 -4
  112. data/docs/doc/Doing/StringTags.html +3 -3
  113. data/docs/doc/Doing/StringTransform.html +3 -3
  114. data/docs/doc/Doing/StringTruncate.html +3 -3
  115. data/docs/doc/Doing/StringURL.html +3 -3
  116. data/docs/doc/Doing/SymbolNormalize.html +5 -5
  117. data/docs/doc/Doing/TaskPaperExport.html +4 -4
  118. data/docs/doc/Doing/TemplateExport.html +5 -5
  119. data/docs/doc/Doing/TemplateString.html +7 -7
  120. data/docs/doc/Doing/TimingImport.html +4 -4
  121. data/docs/doc/Doing/Types.html +3 -3
  122. data/docs/doc/Doing/Util/Backup.html +4 -17
  123. data/docs/doc/Doing/Util.html +56 -61
  124. data/docs/doc/Doing/Version.html +3 -3
  125. data/docs/doc/Doing/WWID.html +6 -4
  126. data/docs/doc/Doing.html +4 -4
  127. data/docs/doc/FalseClass.html +3 -3
  128. data/docs/doc/GLI/Commands/Help.html +5 -5
  129. data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +3 -3
  130. data/docs/doc/GLI/Commands.html +3 -3
  131. data/docs/doc/GLI.html +3 -3
  132. data/docs/doc/Hash.html +4 -4
  133. data/docs/doc/Numeric.html +3 -3
  134. data/docs/doc/Object.html +3 -3
  135. data/docs/doc/PhraseParser/Operator.html +3 -3
  136. data/docs/doc/PhraseParser/PhraseClause.html +3 -3
  137. data/docs/doc/PhraseParser/Query.html +3 -3
  138. data/docs/doc/PhraseParser/QueryParser.html +3 -3
  139. data/docs/doc/PhraseParser/QueryTransformer.html +3 -3
  140. data/docs/doc/PhraseParser/TermClause.html +3 -3
  141. data/docs/doc/PhraseParser.html +3 -3
  142. data/docs/doc/Status.html +3 -3
  143. data/docs/doc/String.html +51 -5
  144. data/docs/doc/Symbol.html +3 -3
  145. data/docs/doc/Time.html +3 -3
  146. data/docs/doc/TrueClass.html +3 -3
  147. data/docs/doc/_index.html +4 -4
  148. data/docs/doc/class_list.html +6 -3
  149. data/docs/doc/css/full_list.css +3 -3
  150. data/docs/doc/css/style.css +6 -0
  151. data/docs/doc/file.README.html +3 -3
  152. data/docs/doc/file_list.html +5 -2
  153. data/docs/doc/frames.html +1 -1
  154. data/docs/doc/index.html +3 -3
  155. data/docs/doc/js/app.js +294 -264
  156. data/docs/doc/js/full_list.js +30 -4
  157. data/docs/doc/method_list.html +443 -392
  158. data/docs/doc/top-level-namespace.html +3 -3
  159. data/doing.gemspec +2 -0
  160. data/doing.rdoc +1 -1
  161. data/example_plugin.rb +1 -4
  162. data/lib/doing/add_options.rb +2 -2
  163. data/lib/doing/array/cleanup.rb +2 -0
  164. data/lib/doing/array/nested_hash.rb +2 -0
  165. data/lib/doing/boolean_term_parser.rb +3 -3
  166. data/lib/doing/changelog/changes.rb +4 -5
  167. data/lib/doing/changelog/version.rb +8 -11
  168. data/lib/doing/chronify/array.rb +4 -4
  169. data/lib/doing/chronify/string.rb +5 -4
  170. data/lib/doing/cli_status.rb +7 -2
  171. data/lib/doing/colors.rb +93 -51
  172. data/lib/doing/completion/bash_completion.rb +36 -39
  173. data/lib/doing/completion/completion_string.rb +2 -1
  174. data/lib/doing/completion/fig_completion.rb +33 -33
  175. data/lib/doing/completion/fish_completion.rb +22 -23
  176. data/lib/doing/completion/zsh_completion.rb +5 -5
  177. data/lib/doing/completion.rb +7 -4
  178. data/lib/doing/configuration.rb +21 -13
  179. data/lib/doing/errors.rb +1 -4
  180. data/lib/doing/good.rb +1 -1
  181. data/lib/doing/hash.rb +4 -4
  182. data/lib/doing/help_monkey_patch.rb +1 -1
  183. data/lib/doing/hooks.rb +6 -2
  184. data/lib/doing/item/dates.rb +3 -1
  185. data/lib/doing/item/query.rb +10 -10
  186. data/lib/doing/item/state.rb +2 -0
  187. data/lib/doing/logger.rb +113 -45
  188. data/lib/doing/markdown_document_listener.rb +25 -25
  189. data/lib/doing/normalize.rb +1 -1
  190. data/lib/doing/pager.rb +73 -29
  191. data/lib/doing/plugin_manager.rb +4 -5
  192. data/lib/doing/plugins/export/byday.rb +1 -1
  193. data/lib/doing/plugins/export/dayone_export.rb +28 -27
  194. data/lib/doing/plugins/export/doing_export.rb +1 -1
  195. data/lib/doing/plugins/export/html_export.rb +3 -3
  196. data/lib/doing/plugins/export/json_export.rb +4 -5
  197. data/lib/doing/plugins/export/markdown_export.rb +10 -2
  198. data/lib/doing/plugins/export/taskpaper_export.rb +1 -0
  199. data/lib/doing/plugins/export/template_export.rb +110 -107
  200. data/lib/doing/plugins/import/calendar_import.rb +1 -1
  201. data/lib/doing/plugins/import/doing_import.rb +2 -2
  202. data/lib/doing/plugins/import/timing_import.rb +3 -3
  203. data/lib/doing/prompt/choose.rb +5 -6
  204. data/lib/doing/prompt/fzf.rb +3 -2
  205. data/lib/doing/prompt/input.rb +7 -6
  206. data/lib/doing/prompt/yn.rb +9 -11
  207. data/lib/doing/string/tags.rb +7 -4
  208. data/lib/doing/string/transform.rb +15 -10
  209. data/lib/doing/string/truncate.rb +1 -0
  210. data/lib/doing/string/url.rb +1 -1
  211. data/lib/doing/template_string.rb +13 -9
  212. data/lib/doing/time.rb +4 -2
  213. data/lib/doing/util.rb +12 -11
  214. data/lib/doing/util_backup.rb +29 -26
  215. data/lib/doing/version.rb +3 -1
  216. data/lib/doing/wwid/display.rb +182 -151
  217. data/lib/doing/wwid/editor.rb +13 -12
  218. data/lib/doing/wwid/filetools.rb +13 -11
  219. data/lib/doing/wwid/filter.rb +41 -40
  220. data/lib/doing/wwid/guess.rb +6 -8
  221. data/lib/doing/wwid/interactive.rb +9 -9
  222. data/lib/doing/wwid/modify.rb +53 -53
  223. data/lib/doing/wwid/timers.rb +4 -5
  224. data/lib/doing/wwid/wwid.rb +0 -0
  225. data/lib/doing/wwid/wwidutil.rb +8 -10
  226. data/lib/examples/commands/wiki.rb +2 -0
  227. data/lib/examples/plugins/capture_thing_import.rb +1 -1
  228. data/lib/examples/plugins/say_export.rb +1 -2
  229. data/lib/examples/plugins/wiki_export/wiki_export.rb +3 -4
  230. data/lib/helpers/fzf/test/test_go.rb +5 -5
  231. data/lib/helpers/threaded_tests.rb +20 -20
  232. data/lib/helpers/threaded_tests_string.rb +2 -0
  233. data/rdoc_to_mmd.rb +5 -4
  234. data/rdocfixer.rb +1 -2
  235. data/scripts/deploy.rb +3 -4
  236. data/scripts/generate_bash_completions.rb +40 -43
  237. data/scripts/generate_fish_completions.rb +17 -15
  238. data/scripts/generate_zsh_completions.rb +9 -7
  239. data/scripts/setting_replace.rb +1 -0
  240. data/scripts/sort_commands.rb +4 -2
  241. data/yard_templates/default/method_details/setup.rb +3 -1
  242. metadata +3 -1
@@ -17,130 +17,133 @@ module Doing
17
17
  end
18
18
 
19
19
  def self.render(wwid, items, variables: {})
20
- Doing.logger.benchmark(:template_render, :start)
21
- return if items.nil?
22
-
23
- opt = variables[:options]
24
-
25
- out = ''
26
- items.each do |item|
27
- if opt[:highlight] && item.title =~ /@#{Doing.setting('marker_tag')}\b/i
28
- flag = Doing::Color.send(Doing.setting('marker_color'))
29
- reset = Doing::Color.reset + Doing::Color.default
30
- else
31
- flag = ''
32
- reset = ''
33
- end
20
+ Doing.logger.measure(:template_render) do
21
+ return if items.nil?
22
+
23
+ opt = variables[:options]
24
+
25
+ out = ''
26
+ items.each do |item|
27
+ if opt[:highlight] && item.title =~ /@#{Doing.setting('marker_tag')}\b/i
28
+ flag = Doing::Color.send(Doing.setting('marker_color'))
29
+ reset = Doing::Color.reset + Doing::Color.default
30
+ else
31
+ flag = ''
32
+ reset = ''
33
+ end
34
34
 
35
- placeholders = {}
35
+ placeholders = {}
36
36
 
37
- if !item.note.empty? && Doing.setting('include_notes')
38
- note = item.note.map(&:strip).delete_if(&:empty?)
39
- note.map! { |line| "#{line.sub(/^\t*/, '')} " }
37
+ if !item.note.empty? && Doing.setting('include_notes')
38
+ note = item.note.map(&:strip).delete_if(&:empty?)
39
+ note.map! { |line| "#{line.sub(/^\t*/, '')} " }
40
40
 
41
- if opt[:wrap_width]&.positive?
42
- width = opt[:wrap_width]
43
- note.map! do |line|
44
- line.simple_wrap(width)
45
- # line.chomp.gsub(/(.{1,#{width}})(\s+|\Z)/, "\\1\n")
41
+ if opt[:wrap_width]&.positive?
42
+ width = opt[:wrap_width]
43
+ note.map! do |line|
44
+ line.simple_wrap(width)
45
+ # line.chomp.gsub(/(.{1,#{width}})(\s+|\Z)/, "\\1\n")
46
+ end
47
+ note.delete_if(&:empty?)
46
48
  end
47
- note.delete_if(&:empty?)
49
+ else
50
+ note = []
48
51
  end
49
- else
50
- note = []
51
- end
52
52
 
53
- placeholders['id'] = item.id
53
+ placeholders['id'] = item.id
54
54
 
55
- placeholders['tags'] = item.tags
55
+ placeholders['tags'] = item.tags
56
56
 
57
- placeholders['date'] = item.date.strftime(opt[:format])
57
+ placeholders['date'] = item.date.strftime(opt[:format])
58
58
 
59
- interval = wwid.get_interval(item, record: true, formatted: false) if opt[:times]
60
- if interval
61
- interval = case opt[:interval_format].to_sym
62
- when :human
63
- interval.time_string(format: :hm)
64
- when :text
65
- interval.time_string(format: :clock)
66
- else
67
- interval.time_string(format: opt[:interval_format].to_sym)
68
- end
69
- end
59
+ interval = wwid.get_interval(item, record: true, formatted: false) if opt[:times]
60
+ if interval
61
+ interval = case opt[:interval_format].to_sym
62
+ when :human
63
+ interval.time_string(format: :hm)
64
+ when :text
65
+ interval.time_string(format: :clock)
66
+ else
67
+ interval.time_string(format: opt[:interval_format].to_sym)
68
+ end
69
+ end
70
70
 
71
- interval ||= ''
72
- placeholders['interval'] = interval
73
-
74
- duration = item.duration if opt[:duration]
75
- if duration
76
- duration = case opt[:interval_format].to_sym
77
- when :human
78
- duration.time_string(format: :hm)
79
- when :text
80
- duration.time_string(format: :clock)
81
- else
82
- duration.time_string(format: opt[:interval_format].to_sym)
83
- end
84
- end
85
- duration ||= ''
86
- placeholders['duration'] = duration
87
-
88
- placeholders['shortdate'] = format('%13s', item.date.relative_date)
89
- placeholders['section'] = item.section || ''
90
- placeholders['title'] = item.title
91
- placeholders['note'] = note
92
- placeholders['idnote'] = note.empty? ? '' : "\n#{note.map { |l| "\t\t#{l.strip} " }.join("\n")}"
93
- placeholders['odnote'] = note.empty? ? '' : "\n#{note.map { |l| "#{l.strip} " }.join("\n")}"
94
-
95
- chompnote = []
96
- unless note.empty?
97
- chompnote = note.map do |l|
98
- l.gsub(/\n+/, ' ').gsub(/(^\s*|\s*$)/, '').gsub(/\s+/, ' ')
71
+ interval ||= ''
72
+ placeholders['interval'] = interval
73
+
74
+ duration = item.duration if opt[:duration]
75
+ if duration
76
+ duration = case opt[:interval_format].to_sym
77
+ when :human
78
+ duration.time_string(format: :hm)
79
+ when :text
80
+ duration.time_string(format: :clock)
81
+ else
82
+ duration.time_string(format: opt[:interval_format].to_sym)
83
+ end
99
84
  end
100
- end
101
- placeholders['chompnote'] = chompnote.join(' ')
102
-
103
- template = opt[:template].dup
104
- note_rx = /(?i-m)(?x:^([\s\S]*?)
105
- (%(?:[io]d|(?:\^[\s\S])?
106
- (?:(?:[ _t]|[^a-z0-9])?\d+)?
107
- (?:[\s\S][ _t]?)?)?note)
108
- ([\s\S]*?)$)/
109
- template.sub!(note_rx, '\1\3\2')
110
- output = Doing::TemplateString.new(template,
111
- color: flag,
112
- placeholders: placeholders,
113
- reset: reset,
114
- tags_color: opt[:tags_color],
115
- wrap_width: opt[:wrap_width]).colored
116
-
117
- output.gsub!(/(?<!\\)%(\S)?hr(_under)?/) do
118
- o = ''
119
- TTY::Screen.columns.to_i.times do
120
- char = Regexp.last_match(2).nil? ? '-' : '_'
121
- char = Regexp.last_match(1).nil? ? char : Regexp.last_match(1)
122
- o += char
85
+ duration ||= ''
86
+ placeholders['duration'] = duration
87
+
88
+ placeholders['shortdate'] = format('%13s', item.date.relative_date)
89
+ placeholders['section'] = item.section || ''
90
+ placeholders['title'] = item.title
91
+ placeholders['note'] = note
92
+ placeholders['idnote'] = note.empty? ? '' : "\n#{note.map { |l| "\t\t#{l.strip} " }.join("\n")}"
93
+ placeholders['odnote'] = note.empty? ? '' : "\n#{note.map { |l| "#{l.strip} " }.join("\n")}"
94
+
95
+ chompnote = []
96
+ unless note.empty?
97
+ chompnote = note.map do |l|
98
+ l.gsub(/\n+/, ' ').gsub(/(^\s*|\s*$)/, '').gsub(/\s+/, ' ')
99
+ end
123
100
  end
124
- o
125
- end
126
- output.gsub!(/(?<!\\)%n/, "\n")
127
- output.gsub!(/(?<!\\)%t/, "\t")
101
+ placeholders['chompnote'] = chompnote.join(' ')
102
+
103
+ template = opt[:template].dup
104
+ note_rx = /(?i-m)(?x:^([\s\S]*?)
105
+ (%(?:[io]d|(?:\^[\s\S])?
106
+ (?:(?:[ _t]|[^a-z0-9])?\d+)?
107
+ (?:[\s\S][ _t]?)?)?note)
108
+ ([\s\S]*?)$)/
109
+ template.sub!(note_rx, '\1\3\2')
110
+ output = Doing::TemplateString.new(template,
111
+ color: flag,
112
+ placeholders: placeholders,
113
+ reset: reset,
114
+ tags_color: opt[:tags_color],
115
+ wrap_width: opt[:wrap_width],
116
+ disable_color: opt[:disable_color]).colored
117
+
118
+ output.gsub!(/(?<!\\)%(\S)?hr(_under)?/) do
119
+ o = ''
120
+ TTY::Screen.columns.to_i.times do
121
+ char = Regexp.last_match(2).nil? ? '-' : '_'
122
+ char = Regexp.last_match(1).nil? ? char : Regexp.last_match(1)
123
+ o += char
124
+ end
125
+ o
126
+ end
127
+ output.gsub!(/(?<!\\)%n/, "\n")
128
+ output.gsub!(/(?<!\\)%t/, "\t")
128
129
 
129
- output.gsub!(/\\%/, '%')
130
+ output.gsub!(/\\%/, '%')
130
131
 
131
- output.highlight_search!(opt[:search]) if opt[:output] =~ /^temp/ && opt[:search] && !opt[:not] && opt[:hilite]
132
+ if opt[:output] =~ /^temp/ && opt[:search] && !opt[:not] && opt[:hilite]
133
+ output.highlight_search!(opt[:search])
134
+ end
132
135
 
133
- out += "#{output}\n"
134
- end
136
+ out += "#{output}\n"
137
+ end
135
138
 
136
- # Doing.logger.debug('Template Export:', "#{items.count} items output to template #{opt[:output]}")
137
- if opt[:totals]
138
- out += wwid.tag_times(format: Doing.setting('timer_format').to_sym,
139
- sort_by: opt[:sort_tags],
140
- sort_order: opt[:tag_order])
139
+ # Doing.logger.debug('Template Export:', "#{items.count} items output to template #{opt[:output]}")
140
+ if opt[:totals]
141
+ out += wwid.tag_times(format: Doing.setting('timer_format').to_sym,
142
+ sort_by: opt[:sort_tags],
143
+ sort_order: opt[:tag_order])
144
+ end
145
+ out
141
146
  end
142
- Doing.logger.benchmark(:template_render, :finish)
143
- out
144
147
  end
145
148
 
146
149
  Doing::Plugins.register 'template', :export, self
@@ -79,7 +79,7 @@ module Doing
79
79
 
80
80
  new_items = wwid.filter_items(new_items, opt: options)
81
81
  filtered = total - new_items.count
82
- Doing.logger.debug('Skipped:' , %(#{filtered} items that didn't match filter criteria)) if filtered.positive?
82
+ Doing.logger.debug('Skipped:', %(#{filtered} items that didn't match filter criteria)) if filtered.positive?
83
83
 
84
84
  new_items = wwid.dedup(new_items, no_overlap: options[:no_overlap])
85
85
  dups = filtered - new_items.count
@@ -86,8 +86,8 @@ module Doing
86
86
  wwid.content[old_index] = new_item
87
87
  Hooks.trigger :post_entry_updated, self, new_item, old_item
88
88
  updated += 1
89
- else
90
- imported.push(new_item) if is_match
89
+ elsif is_match
90
+ imported.push(new_item)
91
91
  end
92
92
  end
93
93
 
@@ -79,15 +79,15 @@ module Doing
79
79
  end
80
80
  total = new_items.count
81
81
  skipped = data.count - total
82
- Doing.logger.debug('Skipped:' , %(#{skipped} items, invalid type or no time interval)) if skipped.positive?
82
+ Doing.logger.debug('Skipped:', %(#{skipped} items, invalid type or no time interval)) if skipped.positive?
83
83
 
84
84
  new_items = wwid.filter_items(new_items, opt: options)
85
85
  filtered = skipped - new_items.count
86
- Doing.logger.debug('Skipped:' , %(#{filtered} items that didn't match filter criteria)) if filtered.positive?
86
+ Doing.logger.debug('Skipped:', %(#{filtered} items that didn't match filter criteria)) if filtered.positive?
87
87
 
88
88
  new_items = wwid.dedup(new_items, no_overlap: options[:no_overlap])
89
89
  dups = filtered - new_items.count
90
- Doing.logger.debug('Skipped:' , %(#{dups} items with overlapping times)) if dups.positive?
90
+ Doing.logger.debug('Skipped:', %(#{dups} items with overlapping times)) if dups.positive?
91
91
 
92
92
  new_items.map { |item| Hooks.trigger :pre_entry_add, self, item }
93
93
 
@@ -29,7 +29,7 @@ module Doing
29
29
  options.sort! if sorted
30
30
 
31
31
  res = `echo #{Shellwords.escape(options.join("\n"))}|#{fzf} #{default_args.join(' ')}`
32
- return false if res.strip.size.zero?
32
+ return false if res.strip.empty?
33
33
 
34
34
  res
35
35
  end
@@ -72,10 +72,10 @@ module Doing
72
72
  ]
73
73
  if include_section
74
74
  out.concat([
75
- ' (',
76
- item.section,
77
- ') '
78
- ])
75
+ ' (',
76
+ item.section,
77
+ ') '
78
+ ])
79
79
  end
80
80
  out.join('')
81
81
  end
@@ -98,7 +98,6 @@ module Doing
98
98
  end
99
99
  fzf_args << '-e' if opt.fetch(:exact, false)
100
100
 
101
-
102
101
  unless opt.fetch(:menu)
103
102
  raise InvalidArgument, "Can't skip menu when no query is provided" unless query && !query.empty?
104
103
 
@@ -71,9 +71,10 @@ module Doing
71
71
  end
72
72
  restore_std
73
73
  unless File.exist?(fzf_bin)
74
- Doing.logger.error('fzf:', 'unable to install fzf. You can install manually and Doing will use the system version.')
74
+ Doing.logger.error('fzf:',
75
+ 'unable to install fzf. You can install manually and Doing will use the system version.')
75
76
  Doing.logger.error('fzf:', 'see https://github.com/junegunn/fzf#installation')
76
- raise RuntimeError.new('Error installing fzf, please report at https://github.com/ttscoff/doing/issues')
77
+ raise 'Error installing fzf, please report at https://github.com/ttscoff/doing/issues'
77
78
  end
78
79
 
79
80
  Doing.logger.info('fzf:', "installed to #{fzf}")
@@ -79,11 +79,11 @@ module Doing
79
79
  Readline.completion_append_character = ' '
80
80
  Readline.completion_proc = comp
81
81
  puts format(['%<promptcolor>s%<prompt>s %<textcolor>sEnter a blank line',
82
- '(%<keycolor>sreturn twice%<textcolor>s)',
83
- 'to end editing and save,',
84
- '%<keycolor>sCTRL-C%<textcolor>s to cancel%<reset>s'].join(' '),
85
- { promptcolor: boldgreen, prompt: prompt.sub(/:?$/, ':'),
86
- textcolor: yellow, keycolor: boldwhite, reset: reset })
82
+ '(%<keycolor>sreturn twice%<textcolor>s)',
83
+ 'to end editing and save,',
84
+ '%<keycolor>sCTRL-C%<textcolor>s to cancel%<reset>s'].join(' '),
85
+ { promptcolor: boldgreen, prompt: prompt.sub(/:?$/, ':'),
86
+ textcolor: yellow, keycolor: boldwhite, reset: reset })
87
87
 
88
88
  res = []
89
89
 
@@ -116,7 +116,8 @@ module Doing
116
116
 
117
117
  ask_note = []
118
118
  reader = TTY::Reader.new(interrupt: -> { raise Errors::UserCancelled }, track_history: false)
119
- puts "#{boldgreen(prompt.sub(/:?$/, ':'))} #{yellow('Hit return for a new line, ')}#{boldwhite('enter a blank line (')}#{boldyellow('return twice')}#{boldwhite(') to end editing')}"
119
+ puts "#{boldgreen(prompt.sub(/:?$/,
120
+ ':'))} #{yellow('Hit return for a new line, ')}#{boldwhite('enter a blank line (')}#{boldyellow('return twice')}#{boldwhite(') to end editing')}"
120
121
  loop do
121
122
  res = reader.read_line(green('> '))
122
123
  break if res.strip.empty?
@@ -14,7 +14,7 @@ module Doing
14
14
  ## @return [Boolean] yes or no
15
15
  ##
16
16
  def yn(question, default_response: false)
17
- return @force_answer == :yes ? true : false unless @force_answer.nil?
17
+ return @force_answer == :yes unless @force_answer.nil?
18
18
 
19
19
  $stdin.reopen('/dev/tty')
20
20
 
@@ -31,22 +31,20 @@ module Doing
31
31
  return default unless $stdout.isatty
32
32
 
33
33
  # clear the buffer
34
- if ARGV&.length
35
- ARGV.length.times do
36
- ARGV.shift
37
- end
34
+ ARGV.length&.times do
35
+ ARGV.shift
38
36
  end
39
37
  system 'stty cbreak'
40
38
 
41
- cw = white
42
- cbw = boldwhite
43
- cbg = boldgreen
39
+ cw = Color.white
40
+ cbw = Color.boldwhite
41
+ cbg = Color.boldgreen
44
42
  cd = Color.default
45
43
 
46
- options = unless default.nil?
47
- "#{cw}[#{default ? "#{cbg}Y#{cw}/#{cbw}n" : "#{cbw}y#{cw}/#{cbg}N"}#{cw}]#{cd}"
48
- else
44
+ options = if default.nil?
49
45
  "#{cw}[#{cbw}y#{cw}/#{cbw}n#{cw}]#{cd}"
46
+ else
47
+ "#{cw}[#{default ? "#{cbg}Y#{cw}/#{cbw}n" : "#{cbw}y#{cw}/#{cbg}N"}#{cw}]#{cd}"
50
48
  end
51
49
  $stdout.syswrite "#{cbw}#{question.sub(/\?$/, '')} #{options}#{cbw}?#{cd} "
52
50
  res = $stdin.sysread 1
@@ -111,18 +111,21 @@ module Doing
111
111
  title.tag!(rename_to, value: value, single: single)
112
112
  elsif m
113
113
  title.gsub!(rx) do
114
- rename_to ? "@#{rename_to}#{value.nil? ? m['parens'] : "(#{value})"}" : ''
114
+ if rename_to
115
+ "@#{rename_to}#{value.nil? ? m['parens'] : "(#{value})"}"
116
+ else
117
+ ''
118
+ end
115
119
  end
116
120
 
117
121
  title.dedup_tags!
118
122
  title.chomp!
119
123
 
124
+ f = "@#{tag}".cyan
120
125
  if rename_to
121
- f = "@#{tag}".cyan
122
126
  t = "@#{rename_to}".cyan
123
127
  Doing.logger.write(log_level, 'Tag:', %(renamed #{f} to #{t} in "#{title}"))
124
128
  else
125
- f = "@#{tag}".cyan
126
129
  Doing.logger.write(log_level, 'Tag:', %(removed #{f} from "#{title}"))
127
130
  end
128
131
  else
@@ -145,7 +148,7 @@ module Doing
145
148
 
146
149
  title.dedup_tags!
147
150
  title.chomp!
148
- Doing.logger.write(log_level, 'Tag:', %(added #{('@' + tag).cyan} to "#{title}"))
151
+ Doing.logger.write(log_level, 'Tag:', %(added #{"@#{tag}".cyan} to "#{title}"))
149
152
  end
150
153
 
151
154
  title.gsub(/ +/, ' ')
@@ -45,7 +45,7 @@ module Doing
45
45
  ## @param prefix [String] (Optional) A prefix to add to each line
46
46
  ##
47
47
  def wrap(len, pad: 0, indent: ' ', offset: 0, prefix: '', color: '', after: '', reset: '', pad_first: false)
48
- last_color = color.empty? ? '' : after.last_color
48
+ color.empty? ? '' : after.last_color
49
49
  note_rx = /(?mi)(?<!\\)%(?<width>-?\d+)?(?:\^(?<mchar>.))?(?:(?<ichar>[ _t]|[^a-z0-9])(?<icount>\d+))?(?<prefix>.[ _t]?)?note/
50
50
  note = ''
51
51
  after = after.dup if after.frozen?
@@ -84,13 +84,13 @@ module Doing
84
84
  last_color = ''
85
85
  out[0] = format("%-#{pad}s%s%s", out[0], last_color, after)
86
86
 
87
- out.map.with_index { |l, idx|
88
- if !pad_first && idx == 0
87
+ out.map.with_index do |l, idx|
88
+ if !pad_first && idx.zero?
89
89
  "#{color}#{prefix}#{l}#{last_color}"
90
90
  else
91
91
  "#{left_pad}#{color}#{prefix}#{l}#{last_color}"
92
92
  end
93
- }.join("\n") + " #{note}".chomp
93
+ end.join("\n") + " #{note}".chomp
94
94
  # res.join("\n").strip + last_color + " #{note}".chomp
95
95
  end
96
96
 
@@ -100,9 +100,7 @@ module Doing
100
100
  ## @return Capitalized string
101
101
  ##
102
102
  def cap_first
103
- sub(/^\w/) do |m|
104
- m.upcase
105
- end
103
+ sub(/^\w/, &:upcase)
106
104
  end
107
105
 
108
106
  ##
@@ -166,9 +164,16 @@ module Doing
166
164
  end
167
165
 
168
166
  def titlecase
169
- tr('_', ' ').
170
- gsub(/\s+/, ' ').
171
- gsub(/\b\w/){ $`[-1,1] == "'" ? $& : $&.upcase }
167
+ tr('_', ' ')
168
+ .gsub(/\s+/, ' ')
169
+ .gsub(/\b\w/) do
170
+ if ::Regexp.last_match.pre_match[-1,
171
+ 1] == "'"
172
+ ::Regexp.last_match(0)
173
+ else
174
+ ::Regexp.last_match(0).upcase
175
+ end
176
+ end
172
177
  end
173
178
  end
174
179
  end
@@ -61,6 +61,7 @@ module Doing
61
61
  ##
62
62
  def truncmiddle(len, ellipsis: '...')
63
63
  return self if length <= len
64
+
64
65
  len -= (ellipsis.length / 2).to_i
65
66
  half = (len / 2).to_i
66
67
  start = trunc(half, ellipsis: ellipsis)
@@ -48,7 +48,7 @@ module Doing
48
48
  gsub(%r{(?mi)(?x:
49
49
  (?<!["'\[(\\])
50
50
  (?<protocol>(?:http|https)://)
51
- (?<domain>[\w\-]+(?:\.[\w\-]+)+)
51
+ (?<domain>[\w-]+(?:\.[\w-]+)+)
52
52
  (?<path>[\w\-.,@?^=%&;:/~+#]*[\w\-@^=%&;/~+#])?
53
53
  )}) do |_match|
54
54
  m = Regexp.last_match
@@ -8,11 +8,12 @@ module Doing
8
8
  attr_reader :original
9
9
 
10
10
  include Color
11
- def initialize(string, placeholders: {}, force_color: false, wrap_width: 0, color: '', tags_color: '', reset: '')
11
+ def initialize(string, placeholders: {}, force_color: false, disable_color: false, wrap_width: 0, color: '', tags_color: '', reset: '')
12
12
  Color.coloring = true if force_color
13
+ Color.coloring = false if disable_color
13
14
  @colors = nil
14
15
  @original = string
15
- super(Color.reset + string)
16
+ super(Doing::Color.coloring? ? Color.reset + string : string)
16
17
 
17
18
  placeholders.each { |k, v| fill(k, v, wrap_width: wrap_width, color: color, tags_color: tags_color) }
18
19
  end
@@ -96,10 +97,13 @@ module Doing
96
97
 
97
98
  def fill(placeholder, value, wrap_width: 0, color: '', tags_color: '', reset: '')
98
99
  reparse
99
- rx = /(?mi)(?<!\\)%(?<width>-?\d+)?(?:\^(?<mchar>.))?(?:(?<ichar>[ _t]|[^a-z0-9])(?<icount>\d+))?(?<prefix>.[ _t]?)?#{placeholder.sub(/^%/, '')}(?<after>.*?)$/
100
+ rx = /(?mi)(?<!\\)%(?<width>-?\d+)?(?:\^(?<mchar>.))?(?:(?<ichar>[ _t]|[^a-z0-9])(?<icount>\d+))?(?<prefix>.[ _t]?)?#{placeholder.sub(
101
+ /^%/, ''
102
+ )}(?<after>.*?)$/
100
103
  ph = raw.match(rx)
101
104
 
102
105
  return unless ph
106
+
103
107
  placeholder_offset = ph.begin(0)
104
108
  last_colors = parsed_colors[:colors].select { |v| v[:index] <= placeholder_offset + 4 }
105
109
 
@@ -148,13 +152,11 @@ module Doing
148
152
  after: after,
149
153
  reset: reset,
150
154
  pad_first: false)
151
- out.highlight_tags!(tags_color, last_color: color) if tags_color && !tags_color.empty?
152
- out
153
155
  else
154
156
  out = format("%s%s%#{pad}s%s", prefix, color, value.gsub(/%/, '\%').sub(/\s*$/, ''), after)
155
- out.highlight_tags!(tags_color, last_color: color) if tags_color && !tags_color.empty?
156
- out
157
157
  end
158
+ out.highlight_tags!(tags_color, last_color: color) if tags_color && !tags_color.empty?
159
+ out
158
160
  elsif placeholder =~ /^note/
159
161
  if wrap_width.positive? || pad.positive?
160
162
  width = pad.positive? ? pad : wrap_width
@@ -162,14 +164,16 @@ module Doing
162
164
  if l.empty?
163
165
  ' '
164
166
  else
165
- line = l.gsub(/%/, '\%').strip.wrap(width, pad: pad, indent: indent, offset: 0, prefix: prefix, color: last_color, after: after, reset: reset, pad_first: true)
167
+ line = l.gsub(/%/, '\%').strip.wrap(width, pad: pad, indent: indent, offset: 0, prefix: prefix,
168
+ color: last_color, after: after, reset: reset, pad_first: true)
166
169
  line.highlight_tags!(tags_color, last_color: last_color) unless !tags_color || !tags_color.good?
167
170
  "#{line} "
168
171
  end
169
172
  end.join("\n")
170
173
  "\n#{last_color}#{mark}#{outstring} "
171
174
  else
172
- out = format("\n%s%s%s%#{pad}s%s", indent, prefix, last_color, value.join("\n#{indent}#{prefix}").gsub(/%/, '\%').sub(/\s*$/, ''), after)
175
+ out = format("\n%s%s%s%#{pad}s%s", indent, prefix, last_color,
176
+ value.join("\n#{indent}#{prefix}").gsub(/%/, '\%').sub(/\s*$/, ''), after)
173
177
  out.highlight_tags!(tags_color, last_color: last_color) if tags_color && !tags_color.empty?
174
178
  out
175
179
  end
data/lib/doing/time.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doing
2
4
  ##
3
5
  ## Date helpers
@@ -35,7 +37,7 @@ module Doing
35
37
  h = (m / 60).floor
36
38
  m = (m % 60).floor
37
39
  d = (h / 24).floor
38
- h = h % 24
40
+ h %= 24
39
41
 
40
42
  output = []
41
43
  output.push("#{d} #{'day'.to_p(d)}") if d.positive?
@@ -58,7 +60,7 @@ module Doing
58
60
  "Yesterday at #{strftime('%_I:%M:%S%P')}"
59
61
  elsif self > (Date.today - 6).to_time
60
62
  strftime('%a %I:%M:%S%P')
61
- elsif self.year == Date.today.year
63
+ elsif year == Date.today.year
62
64
  strftime('%m/%d %I:%M:%S%P')
63
65
  else
64
66
  strftime('%m/%d/%Y %I:%M:%S%P')
data/lib/doing/util.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Doing
4
4
  # Utilities
5
5
  module Util
6
- extend self
6
+ module_function
7
7
 
8
8
  def user_home
9
9
  if Dir.respond_to?('home')
@@ -119,19 +119,20 @@ module Doing
119
119
  puts content
120
120
  return
121
121
  end
122
- Doing.logger.benchmark(:write_file, :start)
123
- file = File.expand_path(file)
122
+ Doing.logger.measure(:write_file) do
123
+ file = File.expand_path(file)
124
124
 
125
- Backup.write_backup(file) if backup
125
+ Backup.write_backup(file) if backup
126
126
 
127
- File.open(file, 'w+') do |f|
128
- f.puts content
129
- Doing.logger.debug('Write:', "File written: #{file}")
127
+ File.open(file, 'w+') do |f|
128
+ f.puts content
129
+ Doing.logger.debug('Write:', "File written: #{file}")
130
+ end
131
+
132
+ Doing.logger.measure(:_post_write_hook) do
133
+ Hooks.trigger :post_write, file
134
+ end
130
135
  end
131
- Doing.logger.benchmark(:_post_write_hook, :start)
132
- Hooks.trigger :post_write, file
133
- Doing.logger.benchmark(:_post_write_hook, :finish)
134
- Doing.logger.benchmark(:write_file, :finish)
135
136
  end
136
137
 
137
138
  def safe_load_file(filename)