doing 2.1.45 → 2.1.46
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.irbrc +3 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/bin/commands/reset.rb +6 -4
- data/docs/doc/Array.html +1 -1
- data/docs/doc/BooleanTermParser/Clause.html +1 -1
- data/docs/doc/BooleanTermParser/Operator.html +1 -1
- data/docs/doc/BooleanTermParser/Query.html +1 -1
- data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
- data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
- data/docs/doc/BooleanTermParser.html +1 -1
- data/docs/doc/Doing/ArrayCleanup.html +1 -1
- data/docs/doc/Doing/ArrayNestedHash.html +1 -1
- data/docs/doc/Doing/ArrayTags.html +1 -1
- data/docs/doc/Doing/CSVExport.html +1 -1
- data/docs/doc/Doing/CalendarImport.html +1 -1
- data/docs/doc/Doing/Change.html +1 -1
- data/docs/doc/Doing/Changes.html +1 -1
- data/docs/doc/Doing/ChronifyArray.html +1 -1
- data/docs/doc/Doing/ChronifyNumeric.html +1 -1
- data/docs/doc/Doing/ChronifyString.html +1 -1
- data/docs/doc/Doing/Color.html +1 -1
- data/docs/doc/Doing/Completion/BashCompletions.html +1 -1
- data/docs/doc/Doing/Completion/FishCompletions.html +1 -1
- data/docs/doc/Doing/Completion/StringUtils.html +1 -1
- data/docs/doc/Doing/Completion/ZshCompletions.html +1 -1
- data/docs/doc/Doing/Completion.html +1 -1
- data/docs/doc/Doing/Configuration.html +1 -1
- data/docs/doc/Doing/DayOneRenderer.html +1 -1
- data/docs/doc/Doing/DayoneExport.html +1 -1
- data/docs/doc/Doing/DoingImport.html +1 -1
- data/docs/doc/Doing/Entry.html +1 -1
- data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
- data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
- data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
- data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
- data/docs/doc/Doing/Errors/HistoryLimitError.html +1 -1
- data/docs/doc/Doing/Errors/InvalidPlugin.html +1 -1
- data/docs/doc/Doing/Errors/MissingBackupFile.html +1 -1
- data/docs/doc/Doing/Errors/NoResults.html +1 -1
- data/docs/doc/Doing/Errors/PluginException.html +1 -1
- data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
- data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
- data/docs/doc/Doing/Errors.html +1 -1
- data/docs/doc/Doing/HTMLExport.html +1 -1
- data/docs/doc/Doing/Hooks.html +1 -1
- data/docs/doc/Doing/Item.html +75 -36
- data/docs/doc/Doing/ItemDates.html +1 -1
- data/docs/doc/Doing/ItemQuery.html +1 -1
- data/docs/doc/Doing/ItemState.html +1 -1
- data/docs/doc/Doing/ItemTags.html +1 -1
- data/docs/doc/Doing/Items.html +129 -1
- data/docs/doc/Doing/JSONExport.html +1 -1
- data/docs/doc/Doing/Logger.html +1 -1
- data/docs/doc/Doing/MarkdownExport.html +1 -1
- data/docs/doc/Doing/Note.html +1 -1
- data/docs/doc/Doing/Pager.html +1 -1
- data/docs/doc/Doing/Plugins.html +1 -1
- data/docs/doc/Doing/Prompt.html +1 -1
- data/docs/doc/Doing/PromptChoose.html +1 -1
- data/docs/doc/Doing/PromptFZF.html +1 -1
- data/docs/doc/Doing/PromptInput.html +1 -1
- data/docs/doc/Doing/PromptSTD.html +1 -1
- data/docs/doc/Doing/PromptYN.html +1 -1
- data/docs/doc/Doing/Section.html +1 -1
- data/docs/doc/Doing/StringHighlight.html +1 -1
- data/docs/doc/Doing/StringNormalize.html +1 -1
- data/docs/doc/Doing/StringQuery.html +1 -1
- data/docs/doc/Doing/StringTags.html +1 -1
- data/docs/doc/Doing/StringTransform.html +1 -1
- data/docs/doc/Doing/StringTruncate.html +1 -1
- data/docs/doc/Doing/StringURL.html +1 -1
- data/docs/doc/Doing/SymbolNormalize.html +1 -1
- data/docs/doc/Doing/TaskPaperExport.html +1 -1
- data/docs/doc/Doing/TemplateExport.html +1 -1
- data/docs/doc/Doing/TemplateString.html +2 -2
- data/docs/doc/Doing/TimingImport.html +1 -1
- data/docs/doc/Doing/Types.html +1 -1
- data/docs/doc/Doing/Util/Backup.html +1 -1
- data/docs/doc/Doing/Util.html +2 -2
- data/docs/doc/Doing/Version.html +1 -1
- data/docs/doc/Doing/WWID.html +1 -1
- data/docs/doc/Doing.html +4 -4
- data/docs/doc/FalseClass.html +1 -1
- data/docs/doc/GLI/Commands/Help.html +1 -1
- data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
- data/docs/doc/GLI/Commands.html +1 -1
- data/docs/doc/GLI.html +1 -1
- data/docs/doc/Hash.html +1 -1
- data/docs/doc/Numeric.html +1 -1
- data/docs/doc/Object.html +1 -1
- data/docs/doc/PhraseParser/Operator.html +1 -1
- data/docs/doc/PhraseParser/PhraseClause.html +1 -1
- data/docs/doc/PhraseParser/Query.html +1 -1
- data/docs/doc/PhraseParser/QueryParser.html +1 -1
- data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
- data/docs/doc/PhraseParser/TermClause.html +1 -1
- data/docs/doc/PhraseParser.html +1 -1
- data/docs/doc/Status.html +1 -1
- data/docs/doc/String.html +63 -1
- data/docs/doc/Symbol.html +1 -1
- data/docs/doc/Time.html +1 -1
- data/docs/doc/TrueClass.html +1 -1
- data/docs/doc/_index.html +8 -1
- data/docs/doc/class_list.html +1 -1
- data/docs/doc/file.README.html +2 -2
- data/docs/doc/index.html +2 -2
- data/docs/doc/method_list.html +409 -361
- data/docs/doc/top-level-namespace.html +1 -1
- data/doing.rdoc +3 -3
- data/lib/doing/item/item.rb +7 -8
- data/lib/doing/items/items.rb +24 -0
- data/lib/doing/plugins/export/json_export.rb +16 -2
- data/lib/doing/plugins/import/json_import.rb +93 -0
- data/lib/doing/string/string.rb +9 -0
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid/filetools.rb +3 -2
- data/lib/doing/wwid/filter.rb +2 -2
- data/lib/doing.rb +1 -0
- metadata +3 -2
@@ -216,7 +216,7 @@
|
|
216
216
|
</div>
|
217
217
|
|
218
218
|
<div id="footer">
|
219
|
-
Generated on
|
219
|
+
Generated on Wed Mar 23 08:25:50 2022 by
|
220
220
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
221
221
|
0.9.27 (ruby-3.0.1).
|
222
222
|
</div>
|
data/doing.rdoc
CHANGED
@@ -5,7 +5,7 @@ record of what you've been doing, complete with tag-based time tracking. The
|
|
5
5
|
command line tool allows you to add entries, annotate with tags and notes, and
|
6
6
|
view your entries with myriad options, with a focus on a "natural" language syntax.
|
7
7
|
|
8
|
-
v2.1.
|
8
|
+
v2.1.46
|
9
9
|
|
10
10
|
=== Global Options
|
11
11
|
=== --config_file arg
|
@@ -1055,7 +1055,7 @@ List commands one per line, to assist with shell completion
|
|
1055
1055
|
==== Command: <tt>import PATH</tt>
|
1056
1056
|
Import entries from an external source
|
1057
1057
|
|
1058
|
-
Imports entries from other sources. Available plugins: calendar, capturething, doing, timing
|
1058
|
+
Imports entries from other sources. Available plugins: calendar, capturething, doing, json, timing
|
1059
1059
|
===== Options
|
1060
1060
|
===== --after DATE_STRING
|
1061
1061
|
|
@@ -1123,7 +1123,7 @@ Tag all imported entries
|
|
1123
1123
|
|
1124
1124
|
===== --type TYPE
|
1125
1125
|
|
1126
|
-
Import type (calendar|capturething|doing|timing)
|
1126
|
+
Import type (calendar|capturething|doing|json|timing)
|
1127
1127
|
|
1128
1128
|
[Default Value] doing
|
1129
1129
|
|
data/lib/doing/item/item.rb
CHANGED
@@ -15,7 +15,7 @@ module Doing
|
|
15
15
|
include ItemState
|
16
16
|
include ItemTags
|
17
17
|
|
18
|
-
attr_accessor :date, :title, :section, :note
|
18
|
+
attr_accessor :date, :title, :section, :note, :id
|
19
19
|
|
20
20
|
# attr_reader :id
|
21
21
|
|
@@ -31,19 +31,18 @@ module Doing
|
|
31
31
|
## the item belongs
|
32
32
|
## @param note [Array or String] The note
|
33
33
|
## (optional)
|
34
|
+
## @param id MD5 identifier
|
34
35
|
##
|
35
|
-
def initialize(date, title, section, note = nil)
|
36
|
+
def initialize(date, title, section, note = nil, id = nil)
|
36
37
|
@date = date.is_a?(Time) ? date : Time.parse(date)
|
37
38
|
@title = title
|
38
39
|
@section = section
|
39
40
|
@note = Note.new(note)
|
41
|
+
@id = id&.valid_id? ? id.strip : gen_id
|
40
42
|
end
|
41
43
|
|
42
|
-
|
43
|
-
|
44
|
-
# @return [String] entry hash
|
45
|
-
def id
|
46
|
-
@id ||= (@date.to_s + @title + @section).hash
|
44
|
+
def gen_id
|
45
|
+
Digest::MD5.hexdigest(to_s)
|
47
46
|
end
|
48
47
|
|
49
48
|
##
|
@@ -91,7 +90,7 @@ module Doing
|
|
91
90
|
|
92
91
|
# outputs item in Doing file format, including leading tab
|
93
92
|
def to_s
|
94
|
-
"\t- #{@date.strftime('%Y-%m-%d %H:%M')} | #{@title}
|
93
|
+
"\t- #{@date.strftime('%Y-%m-%d %H:%M')} | #{@title} <#{@id}>#{@note.good? ? "\n#{@note}" : ''}"
|
95
94
|
end
|
96
95
|
|
97
96
|
##
|
data/lib/doing/items/items.rb
CHANGED
@@ -35,6 +35,30 @@ module Doing
|
|
35
35
|
includes
|
36
36
|
end
|
37
37
|
|
38
|
+
# Find an item by ID
|
39
|
+
#
|
40
|
+
# @param id The identifier to match
|
41
|
+
#
|
42
|
+
def find_id(id)
|
43
|
+
select { |item| item.id == id }[0]
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
## Return the index for an entry matching ID
|
48
|
+
##
|
49
|
+
## @param id The identifier to match
|
50
|
+
##
|
51
|
+
def index_for_id(id)
|
52
|
+
i = nil
|
53
|
+
each_with_index do |item, idx|
|
54
|
+
if item.id == id
|
55
|
+
i = idx
|
56
|
+
break
|
57
|
+
end
|
58
|
+
end
|
59
|
+
i
|
60
|
+
end
|
61
|
+
|
38
62
|
# Output sections and items in Doing file format
|
39
63
|
def to_s
|
40
64
|
out = []
|
@@ -15,7 +15,18 @@ module Doing
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.render(wwid, items, variables: {})
|
18
|
-
|
18
|
+
if items.nil? || items.empty?
|
19
|
+
return case variables[:options][:output]
|
20
|
+
when 'json'
|
21
|
+
{
|
22
|
+
'section' => '',
|
23
|
+
'items' => [],
|
24
|
+
'timers' => ""
|
25
|
+
}.to_json
|
26
|
+
when 'timeline'
|
27
|
+
"<html></html>"
|
28
|
+
end
|
29
|
+
end
|
19
30
|
|
20
31
|
opt = variables[:options]
|
21
32
|
opt[:output] = case opt[:output]
|
@@ -25,6 +36,7 @@ module Doing
|
|
25
36
|
'json'
|
26
37
|
end
|
27
38
|
items_out = []
|
39
|
+
|
28
40
|
last_date = items[-1].date + (60 * 60 * 24)
|
29
41
|
max = last_date.strftime('%F')
|
30
42
|
min = items[0].date.strftime('%F')
|
@@ -51,10 +63,12 @@ module Doing
|
|
51
63
|
date: i.date,
|
52
64
|
end_date: end_date,
|
53
65
|
title: title.strip, #+ " #{note}"
|
66
|
+
section: i.section,
|
54
67
|
note: note.to_s(prefix: ''),
|
55
68
|
time: interval.time_string(format: :clock),
|
56
69
|
duration: duration.time_string(format: :clock),
|
57
|
-
tags: tags
|
70
|
+
tags: tags,
|
71
|
+
id: i.id
|
58
72
|
}
|
59
73
|
|
60
74
|
attributes.each { |attr, val| i[attr.to_sym] = val }
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# title: JSON Import
|
4
|
+
# description: Import entries from a Doing JSON export
|
5
|
+
# author: Brett Terpstra
|
6
|
+
# url: https://brettterpstra.com
|
7
|
+
module Doing
|
8
|
+
class JSONImport
|
9
|
+
include Doing::Util
|
10
|
+
|
11
|
+
def self.settings
|
12
|
+
{
|
13
|
+
trigger: 'json'
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
## Imports a Timing report
|
19
|
+
##
|
20
|
+
## @param wwid [WWID] The wwid object
|
21
|
+
## @param path [String] Path to JSON report
|
22
|
+
## file
|
23
|
+
## @param options [Hash] Additional Options
|
24
|
+
##
|
25
|
+
def self.import(wwid, path, options: {})
|
26
|
+
exit_now! 'Path to JSON export required' if path.nil?
|
27
|
+
options[:no_overlap] ||= false
|
28
|
+
options[:autotag] ||= Doing.auto_tag
|
29
|
+
|
30
|
+
exit_now! 'File not found' unless File.exist?(File.expand_path(path))
|
31
|
+
|
32
|
+
updated = 0
|
33
|
+
added = 0
|
34
|
+
skipped = 0
|
35
|
+
|
36
|
+
data = JSON.parse(IO.read(File.expand_path(path)))
|
37
|
+
new_items = []
|
38
|
+
new_section = options[:section] || Doing.setting('current_section')
|
39
|
+
|
40
|
+
data['items'].each do |entry|
|
41
|
+
title = entry['title']
|
42
|
+
date = Time.parse(entry['date'])
|
43
|
+
date ||= entry['date'].chronify
|
44
|
+
note = Doing::Note.new(entry['note'])
|
45
|
+
section = if entry['section'].empty?
|
46
|
+
new_section
|
47
|
+
else
|
48
|
+
entry['section']
|
49
|
+
end
|
50
|
+
id = entry.key?('id') ? entry['id'] : nil
|
51
|
+
|
52
|
+
new_item = Doing::Item.new(date, title, section, note, id)
|
53
|
+
|
54
|
+
is_match = true
|
55
|
+
|
56
|
+
if options[:search]
|
57
|
+
is_match = new_item.search(options[:search], case_type: options[:case], negate: options[:not])
|
58
|
+
end
|
59
|
+
|
60
|
+
if is_match && options[:date_filter]
|
61
|
+
is_match = start_time > options[:date_filter][0] && start_time < options[:date_filter][1]
|
62
|
+
is_match = options[:not] ? !is_match : is_match
|
63
|
+
end
|
64
|
+
|
65
|
+
unless is_match
|
66
|
+
skipped += 1
|
67
|
+
next
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
if wwid.content.find_id(new_item.id)
|
72
|
+
old_index = wwid.content.index_for_id(entry['id'])
|
73
|
+
old_item = wwid.content[old_index].clone
|
74
|
+
wwid.content[old_index] = new_item
|
75
|
+
Hooks.trigger :post_entry_updated, self, new_item, old_item
|
76
|
+
updated += 1
|
77
|
+
else
|
78
|
+
Hooks.trigger :pre_entry_add, self, item
|
79
|
+
wwid.content << new_entry
|
80
|
+
Hooks.trigger :post_entry_added, self, item
|
81
|
+
added += 1
|
82
|
+
end
|
83
|
+
end
|
84
|
+
total = new_items.count
|
85
|
+
skipped = data.count - total
|
86
|
+
Doing.logger.debug('Skipped:', %(#{skipped} items)) if skipped.positive?
|
87
|
+
Doing.logger.info('Updated:', %(#{updated} items))
|
88
|
+
Doing.logger.info('Imported:', %(#{added} new items to #{new_section}))
|
89
|
+
end
|
90
|
+
|
91
|
+
Doing::Plugins.register 'json', :import, self
|
92
|
+
end
|
93
|
+
end
|
data/lib/doing/string/string.rb
CHANGED
@@ -16,6 +16,15 @@ class ::String
|
|
16
16
|
include Doing::StringTruncate
|
17
17
|
include Doing::StringURL
|
18
18
|
|
19
|
+
##
|
20
|
+
## Test if string is a valid 32-character MD5 id
|
21
|
+
##
|
22
|
+
## @return [Boolean] string is valid identifier
|
23
|
+
##
|
24
|
+
def valid_id?
|
25
|
+
strip =~ /^[a-z0-9]{32}$/ ? true : false
|
26
|
+
end
|
27
|
+
|
19
28
|
##
|
20
29
|
## Force UTF-8 encoding if available
|
21
30
|
##
|
data/lib/doing/version.rb
CHANGED
data/lib/doing/wwid/filetools.rb
CHANGED
@@ -40,7 +40,7 @@ module Doing
|
|
40
40
|
if line =~ /^(\S[\S ]+):\s*(@[\w\-_.]+\s*)*$/
|
41
41
|
section = Regexp.last_match(1)
|
42
42
|
@content.add_section(Section.new(section, original: line), log: false)
|
43
|
-
elsif line =~ /^\s*- (\d{4}-\d\d-\d\d \d\d:\d\d) \| (
|
43
|
+
elsif line =~ /^\s*- (\d{4}-\d\d-\d\d \d\d:\d\d) \| (.*?)(?: +<([a-z0-9]{32})>)? *$/
|
44
44
|
if section.nil?
|
45
45
|
section = 'Uncategorized'
|
46
46
|
@content.add_section(Section.new(section, original: 'Uncategorized:'), log: false)
|
@@ -48,7 +48,8 @@ module Doing
|
|
48
48
|
|
49
49
|
date = Regexp.last_match(1).strip
|
50
50
|
title = Regexp.last_match(2).strip
|
51
|
-
|
51
|
+
id = Regexp.last_match(3) || nil
|
52
|
+
item = Item.new(date, title, section, [], id)
|
52
53
|
@content.push(item)
|
53
54
|
elsif @content.count.zero?
|
54
55
|
# if content[section].items.length - 1 == current
|
data/lib/doing/wwid/filter.rb
CHANGED
@@ -146,8 +146,8 @@ module Doing
|
|
146
146
|
end
|
147
147
|
|
148
148
|
if keep && opt[:time_filter][0] || opt[:time_filter][1]
|
149
|
-
opt[:time_filter]
|
150
|
-
|
149
|
+
opt[:time_filter].map! { |v| v =~ /(12 *am|midnight)/i ? '00:00' : v }
|
150
|
+
|
151
151
|
start_string = if opt[:time_filter][0].nil?
|
152
152
|
"#{item.date.strftime('%Y-%m-%d')} 00:00"
|
153
153
|
else
|
data/lib/doing.rb
CHANGED
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.
|
4
|
+
version: 2.1.46
|
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-
|
11
|
+
date: 2022-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: github-markup
|
@@ -677,6 +677,7 @@ files:
|
|
677
677
|
- lib/doing/plugins/import/cal_to_json.scpt
|
678
678
|
- lib/doing/plugins/import/calendar_import.rb
|
679
679
|
- lib/doing/plugins/import/doing_import.rb
|
680
|
+
- lib/doing/plugins/import/json_import.rb
|
680
681
|
- lib/doing/plugins/import/timing_import.rb
|
681
682
|
- lib/doing/prompt/choose.rb
|
682
683
|
- lib/doing/prompt/fzf.rb
|