doing 2.1.46 → 2.1.49

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 (134) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +1 -1
  5. data/bin/commands/completion.rb +1 -1
  6. data/bin/commands/config.rb +1 -1
  7. data/bin/commands/last.rb +1 -1
  8. data/bin/commands/now.rb +2 -1
  9. data/bin/commands/recent.rb +1 -1
  10. data/docs/doc/Array.html +1 -1
  11. data/docs/doc/BooleanTermParser/Clause.html +1 -1
  12. data/docs/doc/BooleanTermParser/Operator.html +1 -1
  13. data/docs/doc/BooleanTermParser/Query.html +1 -1
  14. data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
  15. data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
  16. data/docs/doc/BooleanTermParser.html +1 -1
  17. data/docs/doc/Doing/ArrayCleanup.html +1 -1
  18. data/docs/doc/Doing/ArrayNestedHash.html +1 -1
  19. data/docs/doc/Doing/ArrayTags.html +1 -1
  20. data/docs/doc/Doing/CSVExport.html +1 -1
  21. data/docs/doc/Doing/CalendarImport.html +1 -1
  22. data/docs/doc/Doing/Change.html +1 -1
  23. data/docs/doc/Doing/Changes.html +1 -1
  24. data/docs/doc/Doing/ChronifyArray.html +1 -1
  25. data/docs/doc/Doing/ChronifyNumeric.html +1 -1
  26. data/docs/doc/Doing/ChronifyString.html +1 -1
  27. data/docs/doc/Doing/Color.html +1 -1
  28. data/docs/doc/Doing/Completion/BashCompletions.html +1 -1
  29. data/docs/doc/Doing/Completion/FigCompletions.html +445 -0
  30. data/docs/doc/Doing/Completion/FishCompletions.html +1 -1
  31. data/docs/doc/Doing/Completion/StringUtils.html +1 -1
  32. data/docs/doc/Doing/Completion/ZshCompletions.html +1 -1
  33. data/docs/doc/Doing/Completion.html +5 -5
  34. data/docs/doc/Doing/Configuration.html +1 -1
  35. data/docs/doc/Doing/DayOneRenderer.html +1 -1
  36. data/docs/doc/Doing/DayoneExport.html +1 -1
  37. data/docs/doc/Doing/DoingExport.html +206 -0
  38. data/docs/doc/Doing/DoingImport.html +1 -1
  39. data/docs/doc/Doing/Entry.html +1 -1
  40. data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
  41. data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
  42. data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
  43. data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
  44. data/docs/doc/Doing/Errors/HistoryLimitError.html +1 -1
  45. data/docs/doc/Doing/Errors/InvalidPlugin.html +1 -1
  46. data/docs/doc/Doing/Errors/MissingBackupFile.html +1 -1
  47. data/docs/doc/Doing/Errors/NoResults.html +1 -1
  48. data/docs/doc/Doing/Errors/PluginException.html +1 -1
  49. data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
  50. data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
  51. data/docs/doc/Doing/Errors.html +1 -1
  52. data/docs/doc/Doing/HTMLExport.html +1 -1
  53. data/docs/doc/Doing/Hooks.html +1 -1
  54. data/docs/doc/Doing/Item.html +1 -1
  55. data/docs/doc/Doing/ItemDates.html +1 -1
  56. data/docs/doc/Doing/ItemQuery.html +1 -1
  57. data/docs/doc/Doing/ItemState.html +1 -1
  58. data/docs/doc/Doing/ItemTags.html +1 -1
  59. data/docs/doc/Doing/Items.html +1 -1
  60. data/docs/doc/Doing/JSONExport.html +1 -1
  61. data/docs/doc/Doing/JSONImport.html +295 -0
  62. data/docs/doc/Doing/Logger.html +1 -1
  63. data/docs/doc/Doing/MarkdownExport.html +1 -1
  64. data/docs/doc/Doing/Note.html +1 -1
  65. data/docs/doc/Doing/Pager.html +1 -1
  66. data/docs/doc/Doing/Plugins.html +1 -1
  67. data/docs/doc/Doing/Prompt.html +1 -1
  68. data/docs/doc/Doing/PromptChoose.html +1 -1
  69. data/docs/doc/Doing/PromptFZF.html +1 -1
  70. data/docs/doc/Doing/PromptInput.html +1 -1
  71. data/docs/doc/Doing/PromptSTD.html +1 -1
  72. data/docs/doc/Doing/PromptYN.html +1 -1
  73. data/docs/doc/Doing/Section.html +1 -1
  74. data/docs/doc/Doing/StringHighlight.html +1 -1
  75. data/docs/doc/Doing/StringNormalize.html +1 -1
  76. data/docs/doc/Doing/StringQuery.html +1 -1
  77. data/docs/doc/Doing/StringTags.html +1 -1
  78. data/docs/doc/Doing/StringTransform.html +1 -1
  79. data/docs/doc/Doing/StringTruncate.html +1 -1
  80. data/docs/doc/Doing/StringURL.html +1 -1
  81. data/docs/doc/Doing/SymbolNormalize.html +1 -1
  82. data/docs/doc/Doing/TaskPaperExport.html +1 -1
  83. data/docs/doc/Doing/TemplateExport.html +1 -1
  84. data/docs/doc/Doing/TemplateString.html +1 -1
  85. data/docs/doc/Doing/TimingImport.html +1 -1
  86. data/docs/doc/Doing/Types.html +1 -1
  87. data/docs/doc/Doing/Util/Backup.html +1 -1
  88. data/docs/doc/Doing/Util.html +1 -1
  89. data/docs/doc/Doing/Version.html +1 -1
  90. data/docs/doc/Doing/WWID.html +1 -1
  91. data/docs/doc/Doing.html +4 -4
  92. data/docs/doc/FalseClass.html +1 -1
  93. data/docs/doc/GLI/Commands/Help.html +1 -1
  94. data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
  95. data/docs/doc/GLI/Commands.html +1 -1
  96. data/docs/doc/GLI.html +1 -1
  97. data/docs/doc/Hash.html +1 -1
  98. data/docs/doc/Numeric.html +1 -1
  99. data/docs/doc/Object.html +1 -1
  100. data/docs/doc/PhraseParser/Operator.html +1 -1
  101. data/docs/doc/PhraseParser/PhraseClause.html +1 -1
  102. data/docs/doc/PhraseParser/Query.html +1 -1
  103. data/docs/doc/PhraseParser/QueryParser.html +1 -1
  104. data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
  105. data/docs/doc/PhraseParser/TermClause.html +1 -1
  106. data/docs/doc/PhraseParser.html +1 -1
  107. data/docs/doc/Status.html +1 -1
  108. data/docs/doc/String.html +2 -2
  109. data/docs/doc/Symbol.html +1 -1
  110. data/docs/doc/Time.html +1 -1
  111. data/docs/doc/TrueClass.html +1 -1
  112. data/docs/doc/_index.html +15 -1
  113. data/docs/doc/class_list.html +1 -1
  114. data/docs/doc/file.README.html +2 -2
  115. data/docs/doc/index.html +2 -2
  116. data/docs/doc/method_list.html +662 -590
  117. data/docs/doc/top-level-namespace.html +1 -1
  118. data/doing.rdoc +18 -18
  119. data/doing.ts +5911 -0
  120. data/export.doing +0 -0
  121. data/lib/completion/_doing.zsh +31 -31
  122. data/lib/completion/doing.ts +4942 -0
  123. data/lib/doing/add_options.rb +1 -1
  124. data/lib/doing/completion/fig_completion.rb +121 -0
  125. data/lib/doing/completion.rb +14 -4
  126. data/lib/doing/plugin_manager.rb +1 -1
  127. data/lib/doing/plugins/export/doing_export.rb +37 -0
  128. data/lib/doing/plugins/export/template_export.rb +4 -2
  129. data/lib/doing/plugins/import/doing_import.rb +17 -6
  130. data/lib/doing/plugins/import/json_import.rb +1 -0
  131. data/lib/doing/version.rb +1 -1
  132. data/lib/doing/wwid/interactive.rb +2 -1
  133. data/lib/doing/wwid/modify.rb +7 -10
  134. metadata +10 -2
@@ -147,7 +147,7 @@ def add_options(type, cmd, default_template: 'default')
147
147
  cmd.desc "#{action} items that *don't* match search/tag filters"
148
148
  cmd.switch [:not], default_value: false, negatable: false
149
149
 
150
- cmd.desc 'Boolean used to combine multiple tags. Use PATTERN to parse + and - as booleans'
150
+ cmd.desc 'Boolean used to combine multiple tags (AND|OR|NOT). Use PATTERN to parse + and - as booleans'
151
151
  cmd.arg_name 'BOOLEAN'
152
152
  cmd.flag [:bool], must_match: REGEX_BOOL,
153
153
  default_value: :pattern,
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doing
4
+ module Completion
5
+ class ::String
6
+ def sanitize
7
+ gsub(/"/, '\"')
8
+ end
9
+ end
10
+
11
+ # Generate completions for zsh
12
+ class FigCompletions
13
+ attr_accessor :commands, :global_options
14
+
15
+ def generate_helpers
16
+ out=<<~EOFUNCTIONS
17
+ const completionSpec: Fig.Spec = {
18
+ name: "doing",
19
+ description: "A CLI for a What Was I Doing system",
20
+ subcommands: [
21
+ #{generate_subcommand_completions.join("\n ")}
22
+ ],
23
+ };
24
+ export default completionSpec;
25
+ EOFUNCTIONS
26
+ @bar.advance(status: '✅')
27
+ @bar.finish
28
+ out
29
+ end
30
+
31
+ def generate_subcommand_completions
32
+ out = []
33
+ indent = ' '
34
+ @commands.each do |cmd|
35
+ cmd[:commands].each do |c|
36
+ out << <<~EOCOMMAND
37
+ {
38
+ #{indent}name: "#{c}",
39
+ #{indent}description: "#{cmd[:description].sanitize}",
40
+ #{indent}#{generate_subcommand_option_completions(cmd)}
41
+ },
42
+ EOCOMMAND
43
+ end
44
+ end
45
+
46
+ out
47
+ end
48
+
49
+ def generate_subcommand_option_completions(cmd, indent: ' ')
50
+ out = []
51
+
52
+ @bar.advance(status: cmd[:commands].first)
53
+
54
+ data = Completion.get_help_sections(cmd[:commands].first)
55
+
56
+ option_arr = []
57
+
58
+ if data[:command_options]
59
+ Completion.parse_options(data[:command_options]).each do |option|
60
+ next if option.nil?
61
+
62
+ arg = ''
63
+
64
+ if option[:arg]
65
+ arg =<<~EOARG
66
+ args: {
67
+ #{indent} name: "#{option[:arg]}",
68
+ #{indent} description: "#{option[:arg]}",
69
+ #{indent} },
70
+ EOARG
71
+ end
72
+
73
+ if option[:short]
74
+ opt_data =<<~EOOPT
75
+ {
76
+ #{indent} name: ["-#{option[:short]}", "--#{option[:long]}"],
77
+ #{indent} description: "#{option[:description].sanitize}",
78
+ #{indent} #{arg}
79
+ #{indent}},
80
+ EOOPT
81
+ else
82
+ opt_data = <<~EOOPT
83
+ {
84
+ #{indent} name: ["--#{option[:long]}"],
85
+ #{indent} description: "#{option[:description].sanitize}",
86
+ #{indent} #{arg}
87
+ #{indent}},
88
+ EOOPT
89
+ end
90
+
91
+ option_arr << opt_data
92
+
93
+ end
94
+
95
+ cmd_opts = <<~EOCMD
96
+ options: [
97
+ #{indent}#{option_arr.join("\n#{indent}")}
98
+ ],
99
+ EOCMD
100
+ out << cmd_opts
101
+ end
102
+
103
+ out.join("\n")
104
+ end
105
+
106
+ def initialize
107
+ data = Completion.get_help_sections
108
+ @global_options = Completion.parse_options(data[:global_options])
109
+ @commands = Completion.parse_commands(data[:commands])
110
+ @bar = TTY::ProgressBar.new(" \033[0;0;33mGenerating Fig completions: \033[0;35;40m[:bar] :status\033[0m", total: @commands.count + 1, bar_format: :square, hide_cursor: true, status: 'processing subcommands')
111
+ width = TTY::Screen.columns - 45
112
+ @bar.resize(width)
113
+ end
114
+
115
+ def generate_completions
116
+ @bar.start
117
+ generate_helpers
118
+ end
119
+ end
120
+ end
121
+ end
@@ -6,6 +6,7 @@ require_relative 'completion/completion_string'
6
6
  require_relative 'completion/fish_completion'
7
7
  require_relative 'completion/zsh_completion'
8
8
  require_relative 'completion/bash_completion'
9
+ require_relative 'completion/fig_completion'
9
10
 
10
11
  module Doing
11
12
  # Completion script generator
@@ -15,8 +16,8 @@ module Doing
15
16
  COMMAND_RX = /^(?<cmd>[^, \t]+)(?<alias>(?:, [^, \t]+)*)?\s+- (?<desc>.*?)$/.freeze
16
17
 
17
18
  class << self
18
- def get_help_sections(command = '')
19
- res = `doing help #{command}`.strip
19
+ def get_help_sections(command = "")
20
+ res = `doing help #{command}|command cat`.strip
20
21
  scanned = res.scan(SECTIONS_RX)
21
22
  sections = {}
22
23
  scanned.each do |sect|
@@ -85,7 +86,7 @@ module Doing
85
86
  type = normalize_type(type)
86
87
  raise InvalidArgument, 'Unrecognized shell specified' if type == :invalid
87
88
 
88
- return %i[zsh bash fish].each { |t| link_default(t) } if type == :all
89
+ return %i[zsh bash fish fig].each { |t| link_default(t) } if type == :all
89
90
 
90
91
  install_builtin(type)
91
92
 
@@ -98,6 +99,7 @@ module Doing
98
99
 
99
100
  if File.exist?(File.join(default_dir, default_filenames[type]))
100
101
  return unless Doing::Prompt.yn("Update #{type} completion script", default_response: 'n')
102
+
101
103
  end
102
104
 
103
105
  FileUtils.cp(src, default_dir)
@@ -106,6 +108,8 @@ module Doing
106
108
 
107
109
  def normalize_type(type)
108
110
  case type.to_s
111
+ when /^fig/i
112
+ :fig
109
113
  when /^f/i
110
114
  :fish
111
115
  when /^b/i
@@ -123,6 +127,8 @@ module Doing
123
127
 
124
128
  def generate_type(type)
125
129
  generator = case type.to_s
130
+ when /^fig/i
131
+ FigCompletions.new
126
132
  when /^f/i
127
133
  FishCompletions.new
128
134
  when /^b/i
@@ -149,7 +155,7 @@ module Doing
149
155
  end
150
156
 
151
157
  def default_filenames
152
- { zsh: '_doing.zsh', bash: 'doing.bash', fish: 'doing.fish' }
158
+ { zsh: '_doing.zsh', bash: 'doing.bash', fish: 'doing.fish', fig: 'doing.ts' }
153
159
  end
154
160
 
155
161
  def default_file(type)
@@ -188,6 +194,8 @@ module Doing
188
194
  Doing.logger.warn('File written:', 'zsh completions written to lib/completion/_doing.zsh')
189
195
  generate_completion(type: 'bash', file: 'lib/completion/doing.bash', link: false)
190
196
  Doing.logger.warn('File written:', 'bash completions written to lib/completion/doing.bash')
197
+ generate_completion(type: 'fig', file: 'lib/completion/doing.ts', link: false)
198
+ Doing.logger.warn('File written:', 'Fig completions written to lib/completion/doing.ts')
191
199
  end
192
200
 
193
201
  def link_completion_type(type, file)
@@ -197,6 +205,7 @@ module Doing
197
205
  unless dir =~ %r{(\.bash_it/completion|bash_completion/completions)}
198
206
  link_completion(file, ['~/.bash_it/completion/enabled', '/usr/share/bash_completion/completions'], 'doing.bash')
199
207
  end
208
+ when /^fig/i
200
209
  when /^f/i
201
210
  link_completion(file, ['~/.config/fish/completions'], 'doing.fish') unless dir =~ %r{.config/fish/completions}
202
211
  when /^z/i
@@ -214,6 +223,7 @@ module Doing
214
223
 
215
224
  targets.each do |target|
216
225
  next unless File.directory?(File.expand_path(target))
226
+
217
227
  found = true
218
228
 
219
229
  target_file = File.join(File.expand_path(target), filename)
@@ -201,7 +201,7 @@ module Doing
201
201
  plugins[type].each do |_, options|
202
202
  pattern << options[:trigger].normalize_trigger
203
203
  end
204
- Regexp.new("^(?:#{pattern.join('|')})$", true)
204
+ Regexp.new("^(?:#{pattern.sort.uniq.join('|')})$", true)
205
205
  end
206
206
 
207
207
  ##
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ # title: Doing File Export
4
+ # description: Export Doing format data
5
+ # author: Brett Terpstra
6
+ # url: https://brettterpstra.com
7
+ module Doing
8
+ class DoingExport
9
+ def self.settings
10
+ {
11
+ trigger: 'doing'
12
+ }
13
+ end
14
+
15
+ def self.render(wwid, items, variables: {})
16
+ return if items.nil?
17
+
18
+ content = Doing::Items.new
19
+ items.each do |item|
20
+ content.add_section(item.section, log: false)
21
+ content.push(item)
22
+ end
23
+
24
+ out = []
25
+ content.sections.each do |section|
26
+ out.push(section.original)
27
+ is = content.in_section(section.title).sort_by { |i| [i.date, i.title] }
28
+ is.reverse! if Doing.setting('doing_file_sort').normalize_order == :desc
29
+ is.each { |item| out.push(item.to_s) }
30
+ end
31
+
32
+ Doing::Pager.page out.join("\n")
33
+ end
34
+
35
+ Doing::Plugins.register 'doing', :export, self
36
+ end
37
+ end
@@ -12,7 +12,7 @@ module Doing
12
12
 
13
13
  def self.settings
14
14
  {
15
- trigger: 'template|doing'
15
+ trigger: 'template'
16
16
  }
17
17
  end
18
18
 
@@ -50,6 +50,8 @@ module Doing
50
50
  note = []
51
51
  end
52
52
 
53
+ placeholders['id'] = item.id
54
+
53
55
  placeholders['tags'] = item.tags
54
56
 
55
57
  placeholders['date'] = item.date.strftime(opt[:format])
@@ -141,6 +143,6 @@ module Doing
141
143
  out
142
144
  end
143
145
 
144
- Doing::Plugins.register ['template', 'doing'], :export, self
146
+ Doing::Plugins.register 'template', :export, self
145
147
  end
146
148
  end
@@ -29,6 +29,7 @@ module Doing
29
29
  exit_now! 'File not found' unless File.exist?(File.expand_path(path))
30
30
 
31
31
  options[:no_overlap] ||= false
32
+
32
33
  options[:autotag] ||= Doing.auto_tag
33
34
 
34
35
  tags = options[:tag] ? options[:tag].split(/[ ,]+/).map { |t| t.sub(/^@?/, '') } : []
@@ -47,6 +48,7 @@ module Doing
47
48
  Doing.logger.debug('Skipped:', %(#{skipped} items that didn't match filter criteria)) if skipped.positive?
48
49
 
49
50
  imported = []
51
+ updated = 0
50
52
 
51
53
  new_items.each do |item|
52
54
  next if duplicate?(item)
@@ -65,8 +67,7 @@ module Doing
65
67
  section = options[:section] || item.section
66
68
  section ||= Doing.setting('current_section')
67
69
 
68
- new_item = Item.new(item.date, title, section)
69
- new_item.note = item.note
70
+ new_item = Item.new(item.date, title, section, item.note, item.id)
70
71
 
71
72
  is_match = true
72
73
 
@@ -79,13 +80,21 @@ module Doing
79
80
  is_match = options[:not] ? !is_match : is_match
80
81
  end
81
82
 
82
- imported.push(new_item) if is_match
83
+ if wwid.content.find_id(new_item.id)
84
+ old_index = wwid.content.index_for_id(new_item.id)
85
+ old_item = wwid.content[old_index].clone
86
+ wwid.content[old_index] = new_item
87
+ Hooks.trigger :post_entry_updated, self, new_item, old_item
88
+ updated += 1
89
+ else
90
+ imported.push(new_item) if is_match
91
+ end
83
92
  end
84
93
 
85
94
  dups = new_items.count - imported.count
86
95
  Doing.logger.info('Skipped:', %(#{dups} duplicate items)) if dups.positive?
87
96
 
88
- imported = wwid.dedup(imported, no_overlap: !options[:overlap])
97
+ imported = wwid.dedup(imported, no_overlap: options[:no_overlap])
89
98
  overlaps = new_items.count - imported.count - dups
90
99
  Doing.logger.debug('Skipped:', "#{overlaps} items with overlapping times") if overlaps.positive?
91
100
 
@@ -96,6 +105,7 @@ module Doing
96
105
  Hooks.trigger :post_entry_added, self, item
97
106
  end
98
107
 
108
+ Doing.logger.info('Updated:', %(#{updated} items))
99
109
  Doing.logger.info('Imported:', "#{imported.count} items")
100
110
  end
101
111
 
@@ -128,10 +138,11 @@ module Doing
128
138
  when /^(\S[\S ]+):(\s+@[\w\-_.]+(?= |$))*\s*$/
129
139
  section = Regexp.last_match(1)
130
140
  current = 0
131
- when /^\s*- (\d{4}-\d\d-\d\d \d\d:\d\d) \| (.*)/
141
+ when /^\s*- (\d{4}-\d\d-\d\d \d\d:\d\d) \| (.*?)(?: <([a-z0-9]{32})>)? *$/
132
142
  date = Regexp.last_match(1).strip
133
143
  title = Regexp.last_match(2).strip
134
- item = Item.new(date, title, section)
144
+ id = Regexp.last_match(3)
145
+ item = Item.new(date, title, section, nil, id)
135
146
  items.push(item)
136
147
  current += 1
137
148
  when /^\S/
@@ -5,6 +5,7 @@
5
5
  # author: Brett Terpstra
6
6
  # url: https://brettterpstra.com
7
7
  module Doing
8
+ # JSON importer
8
9
  class JSONImport
9
10
  include Doing::Util
10
11
 
data/lib/doing/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Doing
2
- VERSION = '2.1.46'
2
+ VERSION = '2.1.49'
3
3
  end
@@ -355,7 +355,8 @@ module Doing
355
355
  def verify_duration(date, finish_date, title: nil)
356
356
  max_elapsed = Doing.setting('interaction.confirm_longer_than', 0)
357
357
  max_elapsed = max_elapsed.chronify_qty if max_elapsed.is_a?(String)
358
- date = date.chronify(guess: :end, context: :today) if finish_date.is_a?(String)
358
+ date = date.chronify(guess: :end, context: :today) if date.is_a?(String)
359
+ finish_date = finish_date.chronify(guess: :end, context: :today) if finish_date.is_a?(String)
359
360
 
360
361
  elapsed = finish_date - date
361
362
 
@@ -39,7 +39,8 @@ module Doing
39
39
 
40
40
  if opt[:done] && entry.should_finish?
41
41
  if entry.should_time?
42
- entry.tag('done', value: opt[:done])
42
+ finish = opt[:done].is_a?(String) ? opt[:done].chronify(guess: :end, context: :today) : opt[:done]
43
+ entry.tag('done', value: finish)
43
44
  else
44
45
  entry.tag('done')
45
46
  end
@@ -47,15 +48,11 @@ module Doing
47
48
 
48
49
  entry.note = note
49
50
 
50
- items = @content.clone
51
51
  if opt[:timed]
52
- items.reverse!
53
- items.each_with_index do |i, x|
54
- next if i.title =~ / @done/
55
-
56
- finish_date = verify_duration(i.date, opt[:back], title: i.title)
57
- items[x].tag('done', value: finish_date.strftime('%F %R'))
58
- break
52
+ last_item = last_entry({ section: section })
53
+ if last_item.tags?(['done'], :not)
54
+ finish_date = verify_duration(last_item.date, opt[:back], title: last_item.title)
55
+ last_item.tag('done', value: finish_date.strftime('%F %R'))
59
56
  end
60
57
  end
61
58
 
@@ -103,7 +100,7 @@ module Doing
103
100
  def repeat_item(item, opt)
104
101
  opt ||= {}
105
102
  old_item = item.clone
106
- if item.should_finish?
103
+ if item.unfinished? && item.should_finish?
107
104
  if item.should_time?
108
105
  finish_date = verify_duration(item.date, Time.now, title: item.title)
109
106
  item.title.tag!('done', value: finish_date.strftime('%F %R'))
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: doing
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.46
4
+ version: 2.1.49
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-23 00:00:00.000000000 Z
11
+ date: 2022-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: github-markup
@@ -503,6 +503,7 @@ files:
503
503
  - docs/doc/Doing/Color.html
504
504
  - docs/doc/Doing/Completion.html
505
505
  - docs/doc/Doing/Completion/BashCompletions.html
506
+ - docs/doc/Doing/Completion/FigCompletions.html
506
507
  - docs/doc/Doing/Completion/FishCompletions.html
507
508
  - docs/doc/Doing/Completion/StringUtils.html
508
509
  - docs/doc/Doing/Completion/ZshCompletions.html
@@ -510,6 +511,7 @@ files:
510
511
  - docs/doc/Doing/Content.html
511
512
  - docs/doc/Doing/DayOneRenderer.html
512
513
  - docs/doc/Doing/DayoneExport.html
514
+ - docs/doc/Doing/DoingExport.html
513
515
  - docs/doc/Doing/DoingImport.html
514
516
  - docs/doc/Doing/Entry.html
515
517
  - docs/doc/Doing/Errors.html
@@ -533,6 +535,7 @@ files:
533
535
  - docs/doc/Doing/ItemTags.html
534
536
  - docs/doc/Doing/Items.html
535
537
  - docs/doc/Doing/JSONExport.html
538
+ - docs/doc/Doing/JSONImport.html
536
539
  - docs/doc/Doing/LogAdapter.html
537
540
  - docs/doc/Doing/Logger.html
538
541
  - docs/doc/Doing/MarkdownExport.html
@@ -613,7 +616,9 @@ files:
613
616
  - docs/index.md
614
617
  - doing.gemspec
615
618
  - doing.rdoc
619
+ - doing.ts
616
620
  - example_plugin.rb
621
+ - export.doing
617
622
  - generate_completions.sh
618
623
  - img/doing-colors.jpg
619
624
  - img/doing-printf-wrap-800.jpg
@@ -621,6 +626,7 @@ files:
621
626
  - lib/completion/_doing.zsh
622
627
  - lib/completion/doing.bash
623
628
  - lib/completion/doing.fish
629
+ - lib/completion/doing.ts
624
630
  - lib/doing.rb
625
631
  - lib/doing/add_options.rb
626
632
  - lib/doing/array/array.rb
@@ -642,6 +648,7 @@ files:
642
648
  - lib/doing/completion.rb
643
649
  - lib/doing/completion/bash_completion.rb
644
650
  - lib/doing/completion/completion_string.rb
651
+ - lib/doing/completion/fig_completion.rb
645
652
  - lib/doing/completion/fish_completion.rb
646
653
  - lib/doing/completion/zsh_completion.rb
647
654
  - lib/doing/configuration.rb
@@ -669,6 +676,7 @@ files:
669
676
  - lib/doing/plugin_manager.rb
670
677
  - lib/doing/plugins/export/csv_export.rb
671
678
  - lib/doing/plugins/export/dayone_export.rb
679
+ - lib/doing/plugins/export/doing_export.rb
672
680
  - lib/doing/plugins/export/html_export.rb
673
681
  - lib/doing/plugins/export/json_export.rb
674
682
  - lib/doing/plugins/export/markdown_export.rb