doing 2.1.2pre → 2.1.6pre
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.
- checksums.yaml +4 -4
- data/.yardoc/checksums +19 -15
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/.yardopts +1 -1
- data/CHANGELOG.md +62 -14
- data/Gemfile.lock +25 -1
- data/README.md +5 -1
- data/Rakefile +2 -0
- data/bin/doing +429 -142
- data/docs/_config.yml +1 -0
- data/{doc → docs/doc}/Array.html +63 -1
- data/docs/doc/BooleanTermParser/Clause.html +293 -0
- data/docs/doc/BooleanTermParser/Operator.html +172 -0
- data/docs/doc/BooleanTermParser/Query.html +417 -0
- data/docs/doc/BooleanTermParser/QueryParser.html +135 -0
- data/docs/doc/BooleanTermParser/QueryTransformer.html +124 -0
- data/docs/doc/BooleanTermParser.html +115 -0
- data/docs/doc/Doing/CLIFormat.html +131 -0
- data/{doc → docs/doc}/Doing/Color.html +2 -2
- data/{doc → docs/doc}/Doing/Completion.html +1 -1
- data/{doc → docs/doc}/Doing/Configuration.html +163 -69
- data/{doc → docs/doc}/Doing/Content.html +0 -0
- data/{doc → docs/doc}/Doing/Errors/DoingNoTraceError.html +1 -1
- data/{doc → docs/doc}/Doing/Errors/DoingRuntimeError.html +1 -1
- data/{doc → docs/doc}/Doing/Errors/DoingStandardError.html +1 -1
- data/{doc → docs/doc}/Doing/Errors/EmptyInput.html +1 -1
- data/{doc → docs/doc}/Doing/Errors/NoResults.html +1 -1
- data/{doc → docs/doc}/Doing/Errors/PluginException.html +1 -1
- data/{doc → docs/doc}/Doing/Errors/UserCancelled.html +1 -1
- data/{doc → docs/doc}/Doing/Errors/WrongCommand.html +1 -1
- data/{doc → docs/doc}/Doing/Errors.html +1 -1
- data/{doc → docs/doc}/Doing/Hooks.html +1 -1
- data/{doc → docs/doc}/Doing/Item.html +135 -89
- data/{doc → docs/doc}/Doing/Items.html +36 -2
- data/{doc → docs/doc}/Doing/LogAdapter.html +70 -1
- data/{doc → docs/doc}/Doing/Note.html +5 -134
- data/{doc → docs/doc}/Doing/Pager.html +1 -1
- data/{doc → docs/doc}/Doing/Plugins.html +431 -35
- data/{doc → docs/doc}/Doing/Prompt.html +70 -18
- data/{doc → docs/doc}/Doing/Section.html +1 -1
- data/docs/doc/Doing/TemplateString.html +713 -0
- data/docs/doc/Doing/Util/Backup.html +686 -0
- data/{doc → docs/doc}/Doing/Util.html +16 -4
- data/{doc → docs/doc}/Doing/WWID.html +133 -73
- data/{doc → docs/doc}/Doing/WWIDFile.html +0 -0
- data/{doc → docs/doc}/Doing.html +4 -4
- data/{doc → docs/doc}/GLI/Commands/MarkdownDocumentListener.html +1 -1
- data/{doc → docs/doc}/GLI/Commands.html +1 -1
- data/{doc → docs/doc}/GLI.html +1 -1
- data/{doc → docs/doc}/Hash.html +1 -1
- data/docs/doc/PhraseParser/Operator.html +172 -0
- data/docs/doc/PhraseParser/PhraseClause.html +303 -0
- data/docs/doc/PhraseParser/Query.html +495 -0
- data/docs/doc/PhraseParser/QueryParser.html +136 -0
- data/docs/doc/PhraseParser/QueryTransformer.html +124 -0
- data/docs/doc/PhraseParser/TermClause.html +293 -0
- data/docs/doc/PhraseParser.html +115 -0
- data/{doc → docs/doc}/Status.html +1 -1
- data/{doc → docs/doc}/String.html +319 -13
- data/{doc → docs/doc}/Symbol.html +35 -1
- data/{doc → docs/doc}/Time.html +70 -2
- data/{doc → docs/doc}/_index.html +132 -4
- data/docs/doc/class_list.html +51 -0
- data/{doc → docs/doc}/css/common.css +0 -0
- data/{doc → docs/doc}/css/full_list.css +0 -0
- data/{doc → docs/doc}/css/style.css +0 -0
- data/{doc → docs/doc}/file.README.html +6 -2
- data/{doc → docs/doc}/file_list.html +0 -0
- data/{doc → docs/doc}/frames.html +0 -0
- data/{doc → docs/doc}/index.html +6 -2
- data/{doc → docs/doc}/js/app.js +0 -0
- data/{doc → docs/doc}/js/full_list.js +0 -0
- data/{doc → docs/doc}/js/jquery.js +0 -0
- data/{doc → docs/doc}/method_list.html +684 -196
- data/{doc → docs/doc}/top-level-namespace.html +2 -2
- data/docs/index.md +60 -0
- data/doing.gemspec +3 -0
- data/doing.rdoc +222 -74
- data/example_plugin.rb +3 -1
- data/lib/completion/_doing.zsh +53 -41
- data/lib/completion/doing.bash +17 -6
- data/lib/completion/doing.fish +321 -2
- data/lib/doing/array.rb +9 -0
- data/lib/doing/boolean_term_parser.rb +86 -0
- data/lib/doing/completion/fish_completion.rb +46 -3
- data/lib/doing/completion/zsh_completion.rb +1 -1
- data/lib/doing/configuration.rb +48 -21
- data/lib/doing/item.rb +105 -10
- data/lib/doing/items.rb +6 -0
- data/lib/doing/log_adapter.rb +28 -0
- data/lib/doing/note.rb +31 -30
- data/lib/doing/phrase_parser.rb +124 -0
- data/lib/doing/plugin_manager.rb +84 -21
- data/lib/doing/plugins/export/dayone_export.rb +209 -0
- data/lib/doing/plugins/export/html_export.rb +2 -2
- data/lib/doing/plugins/export/json_export.rb +1 -0
- data/lib/doing/plugins/export/markdown_export.rb +1 -1
- data/lib/doing/plugins/export/template_export.rb +94 -86
- data/lib/doing/prompt.rb +26 -15
- data/lib/doing/string.rb +114 -29
- data/lib/doing/string_chronify.rb +5 -1
- data/lib/doing/symbol.rb +4 -0
- data/lib/doing/template_string.rb +197 -0
- data/lib/doing/time.rb +32 -0
- data/lib/doing/util.rb +6 -7
- data/lib/doing/util_backup.rb +287 -0
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +105 -41
- data/lib/doing.rb +9 -0
- data/lib/examples/plugins/say_export.rb +1 -1
- data/lib/examples/plugins/wiki_export/wiki_export.rb +3 -3
- data/lib/templates/doing-dayone-entry.erb +6 -0
- data/lib/templates/doing-dayone.erb +5 -0
- metadata +136 -51
- data/doc/class_list.html +0 -51
data/lib/doing/plugin_manager.rb
CHANGED
|
@@ -28,26 +28,30 @@ module Doing
|
|
|
28
28
|
plugins
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
#
|
|
31
|
+
# Setup the plugin search path
|
|
32
|
+
#
|
|
33
|
+
# @param add_dir [String] optional additional
|
|
34
|
+
# path to include
|
|
35
|
+
#
|
|
36
|
+
# @return [Array] Returns an Array of plugin search paths
|
|
32
37
|
#
|
|
33
|
-
# Returns an Array of plugin search paths
|
|
34
38
|
def plugins_path(add_dir = nil)
|
|
35
39
|
paths = Array(File.join(File.dirname(__FILE__), 'plugins'))
|
|
36
40
|
paths << File.join(add_dir) if add_dir
|
|
37
41
|
paths.map { |d| File.expand_path(d) }
|
|
38
42
|
end
|
|
39
43
|
|
|
40
|
-
|
|
44
|
+
|
|
41
45
|
# Register a plugin
|
|
42
46
|
#
|
|
43
|
-
# param
|
|
44
|
-
#
|
|
45
|
-
# param
|
|
47
|
+
# @param title [String|Array] The name of the
|
|
48
|
+
# plugin (can be an array of names)
|
|
49
|
+
# @param type [Symbol] The plugin type
|
|
50
|
+
# (:import, :export)
|
|
51
|
+
# @param klass [Class] The class responding to
|
|
52
|
+
# :render or :import
|
|
46
53
|
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
# returns: Success boolean
|
|
54
|
+
# @return [Boolean] Success boolean
|
|
51
55
|
#
|
|
52
56
|
def register(title, type, klass)
|
|
53
57
|
type = validate_plugin(title, type, klass)
|
|
@@ -90,6 +94,15 @@ module Doing
|
|
|
90
94
|
type
|
|
91
95
|
end
|
|
92
96
|
|
|
97
|
+
##
|
|
98
|
+
## Converts a partial symbol to a valid plugin type,
|
|
99
|
+
## e.g. :imp => :import
|
|
100
|
+
##
|
|
101
|
+
## @param type [Symbol] the symbol to test
|
|
102
|
+
## @param default [Symbol] fallback value
|
|
103
|
+
##
|
|
104
|
+
## @return [Symbol] :import or :export
|
|
105
|
+
##
|
|
93
106
|
def valid_type(type, default: nil)
|
|
94
107
|
type ||= default
|
|
95
108
|
|
|
@@ -154,10 +167,13 @@ module Doing
|
|
|
154
167
|
end
|
|
155
168
|
|
|
156
169
|
##
|
|
157
|
-
## Return a regular expression of all
|
|
158
|
-
##
|
|
170
|
+
## Return a regular expression of all plugin triggers
|
|
171
|
+
## for type
|
|
172
|
+
##
|
|
173
|
+
## @param type [Symbol] The type :import or
|
|
174
|
+
## :export
|
|
159
175
|
##
|
|
160
|
-
## @
|
|
176
|
+
## @return [Regexp] regular expression
|
|
161
177
|
##
|
|
162
178
|
def plugin_regex(type: :export)
|
|
163
179
|
type = valid_type(type)
|
|
@@ -168,24 +184,43 @@ module Doing
|
|
|
168
184
|
Regexp.new("^(?:#{pattern.join('|')})$", true)
|
|
169
185
|
end
|
|
170
186
|
|
|
187
|
+
##
|
|
188
|
+
## Return array of available template names
|
|
189
|
+
##
|
|
190
|
+
## @param type [Symbol] Plugin type (:import,
|
|
191
|
+
## :export)
|
|
192
|
+
##
|
|
193
|
+
## @return [Array<String>] template names
|
|
194
|
+
##
|
|
171
195
|
def plugin_templates(type: :export)
|
|
172
196
|
type = valid_type(type)
|
|
173
197
|
templates = []
|
|
174
198
|
plugs = plugins[type].clone
|
|
175
199
|
plugs.delete_if { |_t, o| o[:templates].nil? }.each do |_, options|
|
|
176
200
|
options[:templates].each do |t|
|
|
177
|
-
|
|
201
|
+
out = t[:name]
|
|
202
|
+
out += " (#{t[:format]})" if t.key?(:format)
|
|
203
|
+
templates << out
|
|
178
204
|
end
|
|
179
205
|
end
|
|
180
206
|
|
|
181
|
-
templates
|
|
207
|
+
templates.sort.uniq
|
|
182
208
|
end
|
|
183
209
|
|
|
210
|
+
##
|
|
211
|
+
## Return a regular expression of all template
|
|
212
|
+
## triggers for type
|
|
213
|
+
##
|
|
214
|
+
## @param type [Symbol] The type :import or
|
|
215
|
+
## :export
|
|
216
|
+
##
|
|
217
|
+
## @return [Regexp] regular expression
|
|
218
|
+
##
|
|
184
219
|
def template_regex(type: :export)
|
|
185
220
|
type = valid_type(type)
|
|
186
221
|
pattern = []
|
|
187
222
|
plugs = plugins[type].clone
|
|
188
|
-
plugs.delete_if { |
|
|
223
|
+
plugs.delete_if { |_, o| o[:templates].nil? }.each do |_, options|
|
|
189
224
|
options[:templates].each do |t|
|
|
190
225
|
pattern << t[:trigger].normalize_trigger
|
|
191
226
|
end
|
|
@@ -193,16 +228,44 @@ module Doing
|
|
|
193
228
|
Regexp.new("^(?:#{pattern.join('|')})$", true)
|
|
194
229
|
end
|
|
195
230
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
231
|
+
##
|
|
232
|
+
## Find and return the appropriate template for a
|
|
233
|
+
## trigger string. Outputs a string that can be
|
|
234
|
+
## written out to the terminal for redirection
|
|
235
|
+
##
|
|
236
|
+
## @param trigger [String] The trigger to test
|
|
237
|
+
## @param type [Symbol] the plugin type
|
|
238
|
+
## (:import, :export)
|
|
239
|
+
##
|
|
240
|
+
## @return [String] string content of template for trigger
|
|
241
|
+
##
|
|
242
|
+
def template_for_trigger(trigger, type: :export, save_to: nil)
|
|
243
|
+
plugins[valid_type(type)].clone.delete_if { |_t, o| o[:templates].nil? }.each do |_, options|
|
|
200
244
|
options[:templates].each do |t|
|
|
201
|
-
|
|
245
|
+
next unless trigger =~ /^(?:#{t[:trigger].normalize_trigger})$/
|
|
246
|
+
|
|
247
|
+
tpl = options[:class].template(trigger)
|
|
248
|
+
return tpl unless save_to
|
|
249
|
+
|
|
250
|
+
raise PluginException.new('No default filename defined', :export, t[:name]) unless t.key?(:filename)
|
|
251
|
+
|
|
252
|
+
return save_template(tpl, save_to, t[:filename])
|
|
202
253
|
end
|
|
203
254
|
end
|
|
204
255
|
raise Errors::InvalidArgument, "No template type matched \"#{trigger}\""
|
|
205
256
|
end
|
|
257
|
+
|
|
258
|
+
def save_template(tpl, dir, filename)
|
|
259
|
+
dir = File.expand_path(dir)
|
|
260
|
+
FileUtils.mkdir_p(dir) unless File.exist?(dir)
|
|
261
|
+
raise DoingRuntimeError, "Path #{dir} exists but is not a directory" unless File.directory?(dir)
|
|
262
|
+
|
|
263
|
+
file = File.join(dir, filename)
|
|
264
|
+
File.open(file, 'w') do |f|
|
|
265
|
+
f.puts(tpl)
|
|
266
|
+
Doing.logger.warn('File update:', "Template written to #{file}")
|
|
267
|
+
end
|
|
268
|
+
end
|
|
206
269
|
end
|
|
207
270
|
end
|
|
208
271
|
end
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
# title: Day One Export
|
|
6
|
+
# description: Export entries to Day One plist for auto import
|
|
7
|
+
# author: Brett Terpstra
|
|
8
|
+
# url: https://brettterpstra.com
|
|
9
|
+
module Doing
|
|
10
|
+
class DayOneRenderer
|
|
11
|
+
attr_accessor :items, :page_title, :totals
|
|
12
|
+
|
|
13
|
+
def initialize(page_title, items, totals)
|
|
14
|
+
@page_title = page_title
|
|
15
|
+
@items = items
|
|
16
|
+
@totals = totals
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def get_binding
|
|
20
|
+
binding()
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class DayoneExport
|
|
25
|
+
include Doing::Util
|
|
26
|
+
|
|
27
|
+
def self.settings
|
|
28
|
+
{
|
|
29
|
+
trigger: 'day(?:one)?(?:-(?:days?|entries))?',
|
|
30
|
+
templates: [
|
|
31
|
+
{ name: 'dayone', trigger: 'day(?:one)?$', format: 'erb', filename: 'dayone.erb' },
|
|
32
|
+
{ name: 'dayone_entry', trigger: 'day(?:one)-entr(?:y|ies)?$', format: 'erb', filename: 'dayone-entry.erb' }
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.template(trigger)
|
|
38
|
+
case trigger
|
|
39
|
+
when /day(?:one)-entr(?:y|ies)?$/
|
|
40
|
+
IO.read(File.join(File.dirname(__FILE__), '../../../templates/doing-dayone-entry.erb'))
|
|
41
|
+
else
|
|
42
|
+
IO.read(File.join(File.dirname(__FILE__), '../../../templates/doing-dayone.erb'))
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.render(wwid, items, variables: {})
|
|
47
|
+
|
|
48
|
+
return if items.nil?
|
|
49
|
+
|
|
50
|
+
opt = variables[:options]
|
|
51
|
+
trigger = opt[:output]
|
|
52
|
+
digest = case trigger
|
|
53
|
+
when /-days?$/
|
|
54
|
+
:day
|
|
55
|
+
when /-entries$/
|
|
56
|
+
:entries
|
|
57
|
+
else
|
|
58
|
+
:digest
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
all_items = []
|
|
62
|
+
days = {}
|
|
63
|
+
flagged = false
|
|
64
|
+
tags = []
|
|
65
|
+
|
|
66
|
+
items.each do |i|
|
|
67
|
+
day_flagged = false
|
|
68
|
+
date_key = i.date.strftime('%Y-%m-%d')
|
|
69
|
+
|
|
70
|
+
if String.method_defined? :force_encoding
|
|
71
|
+
title = i.title.force_encoding('utf-8').link_urls(format: :markdown)
|
|
72
|
+
note = i.note.map { |line| line.force_encoding('utf-8').strip.link_urls(format: :markdown) } if i.note
|
|
73
|
+
else
|
|
74
|
+
title = i.title.link_urls(format: :markdown)
|
|
75
|
+
note = i.note.map { |line| line.strip.link_urls(format: :markdown) } if i.note
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
title = "#{title} @project(#{i.section})" unless variables[:is_single]
|
|
79
|
+
|
|
80
|
+
tags.concat(i.tag_array).sort!.uniq!
|
|
81
|
+
flagged = day_flagged = true if i.tags?(wwid.config['marker_tag'])
|
|
82
|
+
|
|
83
|
+
interval = wwid.get_interval(i, record: true) if i.title =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
|
|
84
|
+
interval ||= false
|
|
85
|
+
human_time = false
|
|
86
|
+
if interval
|
|
87
|
+
d, h, m = wwid.format_time(wwid.get_interval(i, formatted: false))
|
|
88
|
+
human_times = []
|
|
89
|
+
human_times << format('%<d>d day%<p>s', d: d, p: d == 1 ? '' : 's') if d > 0
|
|
90
|
+
human_times << format('%<h>d hour%<p>s', h: h, p: h == 1 ? '' : 's') if h > 0
|
|
91
|
+
human_times << format('%<m>d minute%<p>s', m: m, p: m == 1 ? '' : 's') if m > 0
|
|
92
|
+
human_time = human_times.join(', ')
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
done = i.tags?('done') ? ' ' : ' '
|
|
96
|
+
|
|
97
|
+
item = {
|
|
98
|
+
date_object: i.date,
|
|
99
|
+
date: i.date.strftime('%a %-I:%M%p'),
|
|
100
|
+
shortdate: i.date.relative_date,
|
|
101
|
+
done: done,
|
|
102
|
+
note: note,
|
|
103
|
+
section: i.section,
|
|
104
|
+
time: interval,
|
|
105
|
+
human_time: human_time,
|
|
106
|
+
title: title.strip,
|
|
107
|
+
starred: day_flagged,
|
|
108
|
+
tags: i.tag_array
|
|
109
|
+
}
|
|
110
|
+
all_items << item
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
if days.key?(date_key)
|
|
114
|
+
days[date_key][:starred] = true if day_flagged
|
|
115
|
+
days[date_key][:tags] = days[date_key][:tags].concat(i.tag_array).sort.uniq
|
|
116
|
+
days[date_key][:entries].push(item)
|
|
117
|
+
else
|
|
118
|
+
days[date_key] ||= { tags: [], entries: [], starred: false }
|
|
119
|
+
days[date_key][:starred] = true if day_flagged
|
|
120
|
+
days[date_key][:tags] = days[date_key][:tags].concat(i.tag_array).sort.uniq
|
|
121
|
+
days[date_key][:entries].push(item)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
template = if wwid.config['export_templates']['dayone'] && File.exist?(File.expand_path(wwid.config['export_templates']['dayone']))
|
|
127
|
+
IO.read(File.expand_path(wwid.config['export_templates']['dayone']))
|
|
128
|
+
else
|
|
129
|
+
self.template('dayone')
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
totals = opt[:totals] ? wwid.tag_times(format: :markdown, sort_by_name: opt[:sort_tags], sort_order: opt[:tag_order]) : ''
|
|
133
|
+
|
|
134
|
+
case digest
|
|
135
|
+
when :day
|
|
136
|
+
days.each do |k, hsh|
|
|
137
|
+
title = "#{k}: #{variables[:page_title]}"
|
|
138
|
+
to_dayone(template: template,
|
|
139
|
+
title: title,
|
|
140
|
+
items: hsh[:entries],
|
|
141
|
+
totals: '',
|
|
142
|
+
date: Time.parse(k),
|
|
143
|
+
tags: tags,
|
|
144
|
+
starred: hsh[:starred])
|
|
145
|
+
end
|
|
146
|
+
when :entries
|
|
147
|
+
entry_template = if wwid.config['export_templates']['dayone_entry'] && File.exist?(File.expand_path(wwid.config['export_templates']['dayone_entry']))
|
|
148
|
+
IO.read(File.expand_path(wwid.config['export_templates']['dayone_entry']))
|
|
149
|
+
else
|
|
150
|
+
self.template('dayone-entry')
|
|
151
|
+
end
|
|
152
|
+
all_items.each do |item|
|
|
153
|
+
to_dayone(template: entry_template,
|
|
154
|
+
title: '',
|
|
155
|
+
items: [item],
|
|
156
|
+
totals: '',
|
|
157
|
+
date: item[:date_object],
|
|
158
|
+
tags: item[:tags],
|
|
159
|
+
starred: item[:starred])
|
|
160
|
+
end
|
|
161
|
+
else
|
|
162
|
+
to_dayone(template: template,
|
|
163
|
+
title: variables[:page_title],
|
|
164
|
+
items: all_items,
|
|
165
|
+
totals: totals,
|
|
166
|
+
date: Time.now,
|
|
167
|
+
tags: tags,
|
|
168
|
+
starred: flagged)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
@out = ''
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def self.to_dayone(template: self.template(nil), title: 'doing', items: [], totals: '', date: Time.now, tags: [], starred: false)
|
|
175
|
+
mdx = DayOneRenderer.new(title, items, totals)
|
|
176
|
+
|
|
177
|
+
engine = ERB.new(template)
|
|
178
|
+
content = engine.result(mdx.get_binding)
|
|
179
|
+
|
|
180
|
+
uuid = SecureRandom.uuid
|
|
181
|
+
# uuid = `uuidgen`.strip
|
|
182
|
+
|
|
183
|
+
plist = {
|
|
184
|
+
'Creation Date' => date,
|
|
185
|
+
'Creator' => { 'Software Agent' => 'Doing/2.0.0' },
|
|
186
|
+
'Entry Text' => content,
|
|
187
|
+
'Starred' => starred,
|
|
188
|
+
'Tags' => tags.sort.uniq.delete_if { |t| t =~ /(done|cancell?ed|from)/ },
|
|
189
|
+
'UUID' => uuid
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
container = File.expand_path('~/Library/Group Containers/')
|
|
193
|
+
dayone_dir = Dir.glob('*.dayoneapp2', base: container).first
|
|
194
|
+
import_dir = File.join(container, dayone_dir, 'Data', 'Auto Import', 'Default Journal.dayone', 'entries')
|
|
195
|
+
FileUtils.mkdir_p(import_dir) unless File.exist?(import_dir)
|
|
196
|
+
entry_file = File.join(import_dir, "#{uuid}.doentry")
|
|
197
|
+
Doing.logger.debug('Day One Export:', "Exporting to #{entry_file}")
|
|
198
|
+
File.open(entry_file, 'w') do |f|
|
|
199
|
+
f.puts plist.to_plist
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
Doing.logger.count(:exported, level: :info, count: items.count, message: '%count %items exported to Day One import folder')
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
Doing::Plugins.register 'dayone', :export, self
|
|
206
|
+
Doing::Plugins.register 'dayone-days', :export, self
|
|
207
|
+
Doing::Plugins.register 'dayone-entries', :export, self
|
|
208
|
+
end
|
|
209
|
+
end
|
|
@@ -12,8 +12,8 @@ module Doing
|
|
|
12
12
|
{
|
|
13
13
|
trigger: 'html?|web(?:page)?',
|
|
14
14
|
templates: [
|
|
15
|
-
{ name: '
|
|
16
|
-
{ name: '
|
|
15
|
+
{ name: 'html', trigger: 'h[ta]ml?|web', format: 'haml', filename: 'html_export.haml' },
|
|
16
|
+
{ name: 'html_style', trigger: 'css|styl(?:e|us)', format: 'css', filename: 'html_export.css' }
|
|
17
17
|
]
|
|
18
18
|
}
|
|
19
19
|
end
|
|
@@ -23,40 +23,36 @@ module Doing
|
|
|
23
23
|
out = ''
|
|
24
24
|
items.each do |item|
|
|
25
25
|
if opt[:highlight] && item.title =~ /@#{wwid.config['marker_tag']}\b/i
|
|
26
|
-
|
|
27
|
-
reset = Doing::Color.default
|
|
26
|
+
flag = Doing::Color.send(wwid.config['marker_color'])
|
|
27
|
+
reset = Doing::Color.reset + Doing::Color.default
|
|
28
28
|
else
|
|
29
|
-
|
|
29
|
+
flag = ''
|
|
30
30
|
reset = ''
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
placeholders = {}
|
|
34
|
+
|
|
33
35
|
if (!item.note.empty?) && wwid.config['include_notes']
|
|
34
36
|
note = item.note.map(&:strip).delete_if(&:empty?)
|
|
35
37
|
note.map! { |line| "#{line.sub(/^\t*/, '')} " }
|
|
36
38
|
|
|
37
39
|
if opt[:wrap_width]&.positive?
|
|
38
40
|
width = opt[:wrap_width]
|
|
39
|
-
note.map!
|
|
40
|
-
|
|
41
|
+
note.map! do |line|
|
|
42
|
+
line.simple_wrap(width)
|
|
43
|
+
# line.chomp.gsub(/(.{1,#{width}})(\s+|\Z)/, "\\1\n")
|
|
44
|
+
end
|
|
45
|
+
note = note.delete_if(&:empty?)
|
|
41
46
|
end
|
|
42
47
|
else
|
|
43
48
|
note = []
|
|
44
49
|
end
|
|
45
50
|
|
|
46
|
-
output
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
else
|
|
52
|
-
m
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
output.sub!(/%(\d+)?date/) do
|
|
57
|
-
pad = Regexp.last_match(1).to_i
|
|
58
|
-
format("%#{pad}s", item.date.strftime(opt[:format]))
|
|
59
|
-
end
|
|
51
|
+
# output.sub!(/%(\d+)?date/) do
|
|
52
|
+
# pad = Regexp.last_match(1).to_i
|
|
53
|
+
# format("%#{pad}s", item.date.strftime(opt[:format]))
|
|
54
|
+
# end
|
|
55
|
+
placeholders['date'] = item.date.strftime(opt[:format])
|
|
60
56
|
|
|
61
57
|
interval = wwid.get_interval(item, record: true, formatted: false) if opt[:times]
|
|
62
58
|
if interval
|
|
@@ -71,7 +67,8 @@ module Doing
|
|
|
71
67
|
end
|
|
72
68
|
|
|
73
69
|
interval ||= ''
|
|
74
|
-
output.sub!(/%interval/, interval)
|
|
70
|
+
# output.sub!(/%interval/, interval)
|
|
71
|
+
placeholders['interval'] = interval
|
|
75
72
|
|
|
76
73
|
duration = item.duration if opt[:duration]
|
|
77
74
|
if duration
|
|
@@ -85,78 +82,89 @@ module Doing
|
|
|
85
82
|
end
|
|
86
83
|
end
|
|
87
84
|
duration ||= ''
|
|
88
|
-
output.sub!(/%duration/, duration)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
#
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
output.
|
|
85
|
+
# output.sub!(/%duration/, duration)
|
|
86
|
+
placeholders['duration'] = duration
|
|
87
|
+
|
|
88
|
+
# output.sub!(/%(\d+)?shortdate/) do
|
|
89
|
+
# pad = Regexp.last_match(1) || 13
|
|
90
|
+
# format("%#{pad}s", item.date.relative_date)
|
|
91
|
+
# end
|
|
92
|
+
placeholders['shortdate'] = format("%13s", item.date.relative_date)
|
|
93
|
+
# output.sub!(/%section/, item.section) if item.section
|
|
94
|
+
placeholders['section'] = item.section || ''
|
|
95
|
+
placeholders['title'] = item.title
|
|
96
|
+
|
|
97
|
+
# title_rx = /(?mi)%(?<width>-?\d+)?(?:(?<ichar>[ _t])(?<icount>\d+))?(?<prefix>.[ _t]?)?title(?<after>.*?)$/
|
|
98
|
+
# title_color = Doing::Color.reset + output.match(/(?mi)^(.*?)(%.*?title)/)[1].last_color
|
|
99
|
+
|
|
100
|
+
# title_offset = Doing::Color.uncolor(output).match(title_rx).begin(0)
|
|
101
|
+
|
|
102
|
+
# output.sub!(title_rx) do
|
|
103
|
+
# m = Regexp.last_match
|
|
104
|
+
|
|
105
|
+
# after = m['after']
|
|
106
|
+
# pad = m['width'].to_i
|
|
107
|
+
# indent = ''
|
|
108
|
+
# if m['ichar']
|
|
109
|
+
# char = m['ichar'] =~ /t/ ? "\t" : ' '
|
|
110
|
+
# indent = char * m['icount'].to_i
|
|
111
|
+
# end
|
|
112
|
+
# prefix = m['prefix']
|
|
113
|
+
# if opt[:wrap_width]&.positive? || pad.positive?
|
|
114
|
+
# width = pad.positive? ? pad : opt[:wrap_width]
|
|
115
|
+
# item.title.wrap(width, pad: pad, indent: indent, offset: title_offset, prefix: prefix, color: title_color, after: after, reset: reset)
|
|
116
|
+
# # flag + item.title.gsub(/(.{#{opt[:wrap_width]}})(?=\s+|\Z)/, "\\1\n ").sub(/\s*$/, '') + reset
|
|
117
|
+
# else
|
|
118
|
+
# format("%s%#{pad}s%s", prefix, item.title.sub(/\s*$/, ''), after)
|
|
119
|
+
# end
|
|
120
|
+
# end
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
placeholders['note'] = note
|
|
125
|
+
placeholders['idnote'] = note.empty? ? '' : "\n#{note.map { |l| "\t\t#{l.strip} " }.join("\n")}"
|
|
126
|
+
placeholders['odnote'] = note.empty? ? '' : "\n#{note.map { |l| "#{l.strip} " }.join("\n")}"
|
|
127
|
+
placeholders['chompnote'] = note.empty? ? '' : note.map { |l| l.gsub(/\n+/, ' ').gsub(/(^\s*|\s*$)/, '').gsub(/\s+/, ' ') }.join(' ')
|
|
128
|
+
|
|
129
|
+
# if note.empty?
|
|
130
|
+
# output.gsub!(/%(chomp|[io]d|(\^.)?(([ _t]|[^a-z0-9])?\d+)?(.[ _t]?)?)?note/, '')
|
|
131
|
+
# else
|
|
132
|
+
# output.sub!(/%note/, "\n#{note.map { |l| "\t#{l.strip} " }.join("\n")}")
|
|
133
|
+
# output.sub!(/%idnote/, "\n#{note.map { |l| "\t\t#{l.strip} " }.join("\n")}")
|
|
134
|
+
# output.sub!(/%odnote/, "\n#{note.map { |l| "#{l.strip} " }.join("\n")}")
|
|
135
|
+
# output.sub!(/(?mi)%(?:\^(?<mchar>.))?(?:(?<ichar>[ _t]|[^a-z0-9])?(?<icount>\d+))?(?<prefix>.[ _t]?)?note/) do
|
|
136
|
+
# m = Regexp.last_match
|
|
137
|
+
# mark = m['mchar'] || ''
|
|
138
|
+
# indent = if m['ichar']
|
|
139
|
+
# char = m['ichar'] =~ /t/ ? "\t" : ' '
|
|
140
|
+
# char * m['icount'].to_i
|
|
141
|
+
# else
|
|
142
|
+
# ''
|
|
143
|
+
# end
|
|
144
|
+
# prefix = m['prefix'] || ''
|
|
145
|
+
# "\n#{note.map { |l| "#{mark}#{indent}#{prefix}#{l.strip} " }.join("\n")}"
|
|
146
|
+
# end
|
|
147
|
+
|
|
148
|
+
# output.sub!(/%chompnote/) do
|
|
149
|
+
# note.map { |l| l.gsub(/\n+/, ' ').gsub(/(^\s*|\s*$)/, '').gsub(/\s+/, ' ') }.join(' ')
|
|
150
|
+
# end
|
|
151
|
+
# end
|
|
152
|
+
|
|
153
|
+
template = opt[:template].dup
|
|
154
|
+
template.sub!(/(?i-m)^([\s\S]*?)(%(?:[io]d|(?:\^[\s\S])?(?:(?:[ _t]|[^a-z0-9])?\d+)?(?:[\s\S][ _t]?)?)?note)([\s\S]*?)$/, '\1\3\2')
|
|
155
|
+
output = Doing::TemplateString.new(template, placeholders: placeholders, wrap_width: opt[:wrap_width], color: flag, tags_color: opt[:tags_color], reset: reset).colored
|
|
156
|
+
|
|
157
|
+
output.gsub!(/(?<!\\)%hr(_under)?/) do
|
|
152
158
|
o = ''
|
|
153
159
|
`tput cols`.to_i.times do
|
|
154
160
|
o += Regexp.last_match(1).nil? ? '-' : '_'
|
|
155
161
|
end
|
|
156
162
|
o
|
|
157
163
|
end
|
|
158
|
-
output.gsub!(
|
|
159
|
-
output.gsub!(
|
|
164
|
+
output.gsub!(/(?<!\\)%n/, "\n")
|
|
165
|
+
output.gsub!(/(?<!\\)%t/, "\t")
|
|
166
|
+
|
|
167
|
+
output.gsub!(/\\%/, '%')
|
|
160
168
|
|
|
161
169
|
out += "#{output}\n"
|
|
162
170
|
end
|