doing 2.0.22 → 2.1.0pre
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 +18 -15
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/CHANGELOG.md +36 -1
- data/Gemfile.lock +8 -1
- data/README.md +7 -1
- data/Rakefile +23 -4
- data/bin/doing +323 -173
- data/doc/Array.html +354 -1
- data/doc/Doing/Color.html +104 -92
- data/doc/Doing/Completion.html +216 -0
- data/doc/Doing/Configuration.html +340 -5
- data/doc/Doing/Content.html +229 -0
- data/doc/Doing/Errors/DoingNoTraceError.html +1 -1
- data/doc/Doing/Errors/DoingRuntimeError.html +1 -1
- data/doc/Doing/Errors/DoingStandardError.html +1 -1
- data/doc/Doing/Errors/EmptyInput.html +1 -1
- data/doc/Doing/Errors/NoResults.html +1 -1
- data/doc/Doing/Errors/PluginException.html +1 -1
- data/doc/Doing/Errors/UserCancelled.html +1 -1
- data/doc/Doing/Errors/WrongCommand.html +1 -1
- data/doc/Doing/Errors.html +1 -1
- data/doc/Doing/Hooks.html +1 -1
- data/doc/Doing/Item.html +337 -49
- data/doc/Doing/Items.html +444 -35
- data/doc/Doing/LogAdapter.html +139 -51
- data/doc/Doing/Note.html +253 -22
- data/doc/Doing/Pager.html +74 -36
- data/doc/Doing/Plugins.html +1 -1
- data/doc/Doing/Prompt.html +674 -0
- data/doc/Doing/Section.html +354 -0
- data/doc/Doing/Util.html +57 -1
- data/doc/Doing/WWID.html +477 -670
- data/doc/Doing/WWIDFile.html +398 -0
- data/doc/Doing.html +5 -5
- data/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
- data/doc/GLI/Commands.html +1 -1
- data/doc/GLI.html +1 -1
- data/doc/Hash.html +97 -1
- data/doc/Status.html +37 -3
- data/doc/String.html +599 -23
- data/doc/Symbol.html +3 -3
- data/doc/Time.html +1 -1
- data/doc/_index.html +22 -1
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +8 -2
- data/doc/index.html +8 -2
- data/doc/method_list.html +453 -173
- data/doc/top-level-namespace.html +1 -1
- data/doing.gemspec +3 -0
- data/doing.rdoc +79 -27
- data/example_plugin.rb +5 -5
- data/lib/completion/_doing.zsh +42 -42
- data/lib/completion/doing.bash +10 -10
- data/lib/completion/doing.fish +1 -280
- data/lib/doing/array.rb +36 -0
- data/lib/doing/colors.rb +70 -66
- data/lib/doing/completion/bash_completion.rb +1 -2
- data/lib/doing/completion/fish_completion.rb +1 -1
- data/lib/doing/completion/zsh_completion.rb +1 -1
- data/lib/doing/completion.rb +6 -0
- data/lib/doing/configuration.rb +134 -23
- data/lib/doing/hash.rb +37 -0
- data/lib/doing/item.rb +77 -12
- data/lib/doing/items.rb +125 -0
- data/lib/doing/log_adapter.rb +58 -4
- data/lib/doing/note.rb +53 -1
- data/lib/doing/pager.rb +49 -38
- data/lib/doing/plugins/export/markdown_export.rb +4 -4
- data/lib/doing/plugins/export/template_export.rb +2 -2
- data/lib/doing/plugins/import/calendar_import.rb +4 -4
- data/lib/doing/plugins/import/doing_import.rb +5 -7
- data/lib/doing/plugins/import/timing_import.rb +3 -3
- data/lib/doing/prompt.rb +206 -0
- data/lib/doing/section.rb +30 -0
- data/lib/doing/string.rb +123 -35
- data/lib/doing/util.rb +14 -6
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +307 -614
- data/lib/doing.rb +6 -2
- data/lib/examples/plugins/capture_thing_import.rb +162 -0
- data/rdoc_to_mmd.rb +14 -8
- data/scripts/generate_bash_completions.rb +1 -1
- data/scripts/generate_fish_completions.rb +1 -1
- data/scripts/generate_zsh_completions.rb +1 -1
- metadata +73 -5
- data/lib/doing/wwidfile.rb +0 -117
data/lib/doing.rb
CHANGED
@@ -7,6 +7,8 @@ require 'pp'
|
|
7
7
|
require 'csv'
|
8
8
|
require 'tempfile'
|
9
9
|
require 'chronic'
|
10
|
+
require 'tty-link'
|
11
|
+
require 'tty-which'
|
10
12
|
# require 'amatch'
|
11
13
|
require 'haml'
|
12
14
|
require 'json'
|
@@ -20,11 +22,13 @@ require 'doing/array'
|
|
20
22
|
require 'doing/symbol'
|
21
23
|
require 'doing/util'
|
22
24
|
require 'doing/configuration'
|
23
|
-
require 'doing/
|
25
|
+
require 'doing/section'
|
26
|
+
require 'doing/items'
|
24
27
|
require 'doing/note'
|
25
|
-
require 'doing/
|
28
|
+
require 'doing/item'
|
26
29
|
require 'doing/wwid'
|
27
30
|
require 'doing/log_adapter'
|
31
|
+
require 'doing/prompt'
|
28
32
|
require 'doing/errors'
|
29
33
|
require 'doing/hooks'
|
30
34
|
require 'doing/plugin_manager'
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# title: Capture Thing Import
|
4
|
+
# description: Import entries from a Capture Thing folder
|
5
|
+
# author: Brett Terpstra
|
6
|
+
# url: https://brettterpstra.com
|
7
|
+
module Doing
|
8
|
+
class CaptureThingImport
|
9
|
+
require 'time'
|
10
|
+
include Doing::Util
|
11
|
+
include Doing::Errors
|
12
|
+
|
13
|
+
def self.settings
|
14
|
+
{
|
15
|
+
trigger: '^cap(?:ture)?(:?thing)?'
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
## Imports a Capture Thing folder
|
21
|
+
##
|
22
|
+
## @param wwid [WWID] WWID object
|
23
|
+
## @param path [String] Path to Capture Thing folder
|
24
|
+
## @param options [Hash] Additional Options
|
25
|
+
##
|
26
|
+
def self.import(wwid, path, options: {})
|
27
|
+
raise InvalidArgument, 'Path to Capture Thing folder required' if path.nil?
|
28
|
+
|
29
|
+
path = File.expand_path(path)
|
30
|
+
|
31
|
+
raise InvalidArgument, 'File not found' unless File.exist?(path)
|
32
|
+
|
33
|
+
raise InvalidArgument, 'Path is not a directory' unless File.directory?(path)
|
34
|
+
|
35
|
+
options[:no_overlap] ||= false
|
36
|
+
options[:autotag] ||= wwid.auto_tag
|
37
|
+
|
38
|
+
tags = options[:tag] ? options[:tag].split(/[ ,]+/).map { |t| t.sub(/^@?/, '') } : []
|
39
|
+
options[:tag] = nil
|
40
|
+
prefix = options[:prefix] || ''
|
41
|
+
|
42
|
+
@old_items = wwid.content.dup
|
43
|
+
|
44
|
+
new_items = read_capture_folder(path)
|
45
|
+
|
46
|
+
total = new_items.count
|
47
|
+
|
48
|
+
options[:count] = 0
|
49
|
+
|
50
|
+
new_items = wwid.filter_items(new_items, opt: options)
|
51
|
+
|
52
|
+
skipped = total - new_items.count
|
53
|
+
Doing.logger.debug('Skipped:' , %(#{skipped} items that didn't match filter criteria)) if skipped.positive?
|
54
|
+
|
55
|
+
imported = []
|
56
|
+
|
57
|
+
new_items.each do |item|
|
58
|
+
next if duplicate?(item)
|
59
|
+
|
60
|
+
title = "#{prefix} #{item.title}"
|
61
|
+
tags.each do |tag|
|
62
|
+
if title =~ /\b#{tag}\b/i
|
63
|
+
title.sub!(/\b#{tag}\b/i, "@#{tag}")
|
64
|
+
else
|
65
|
+
title += " @#{tag}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
title = wwid.autotag(title) if options[:autotag]
|
69
|
+
title.gsub!(/ +/, ' ')
|
70
|
+
title.strip!
|
71
|
+
section = options[:section] || item.section
|
72
|
+
section ||= wwid.config['current_section']
|
73
|
+
|
74
|
+
new_item = Item.new(item.date, title, section)
|
75
|
+
new_item.note = item.note
|
76
|
+
|
77
|
+
imported.push(new_item)
|
78
|
+
end
|
79
|
+
|
80
|
+
dups = new_items.count - imported.count
|
81
|
+
Doing.logger.info('Skipped:', %(#{dups} duplicate items)) if dups.positive?
|
82
|
+
|
83
|
+
imported = wwid.dedup(imported, no_overlap: !options[:overlap])
|
84
|
+
overlaps = new_items.count - imported.count - dups
|
85
|
+
Doing.logger.debug('Skipped:', "#{overlaps} items with overlapping times") if overlaps.positive?
|
86
|
+
|
87
|
+
imported.each do |item|
|
88
|
+
wwid.content.add_section(item.section) unless wwid.content.section?(item.section)
|
89
|
+
wwid.content.push(item)
|
90
|
+
end
|
91
|
+
|
92
|
+
Doing.logger.info('Imported:', "#{imported.count} items")
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.duplicate?(item)
|
96
|
+
@old_items.each do |oi|
|
97
|
+
return true if item.equal?(oi)
|
98
|
+
end
|
99
|
+
|
100
|
+
false
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.parse_entry(date, entry)
|
104
|
+
lines = entry.strip.split(/\n/)
|
105
|
+
|
106
|
+
return nil if lines.nil?
|
107
|
+
|
108
|
+
time_line = lines.shift
|
109
|
+
|
110
|
+
return nil unless time_line =~ /^# (\d+:\d{2} [AP]M)/
|
111
|
+
|
112
|
+
m = time_line.match(/^# (\d+:\d{2} [AP]M)/)
|
113
|
+
|
114
|
+
unless m
|
115
|
+
Doing.logger.debug("Error parsing time #{time_line}")
|
116
|
+
return nil
|
117
|
+
end
|
118
|
+
|
119
|
+
time = m[1]
|
120
|
+
entry_date = Time.parse("#{date} #{time}")
|
121
|
+
|
122
|
+
title = ''
|
123
|
+
note = Note.new
|
124
|
+
lines.each_with_index do |l, i|
|
125
|
+
if l =~ /^-{4,}/
|
126
|
+
note.add(lines.slice(i + 1, lines.count - i))
|
127
|
+
break
|
128
|
+
else
|
129
|
+
title += l
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
Item.new(entry_date, title, nil, note)
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.read_capture_folder(path)
|
137
|
+
folder = File.expand_path(path)
|
138
|
+
|
139
|
+
return nil unless File.exist?(folder) && File.directory?(folder)
|
140
|
+
|
141
|
+
items = []
|
142
|
+
|
143
|
+
files = Dir.glob('**/*.md', base: folder)
|
144
|
+
|
145
|
+
files.each do |file|
|
146
|
+
date = File.basename(file, '.md').match(/^(\d{4}-\d{2}-\d{2})/)[1]
|
147
|
+
input = IO.read(File.join(folder, file))
|
148
|
+
input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
|
149
|
+
entries = input.split(/^\* \* \* \* \*$/).map(&:strip).delete_if(&:empty?)
|
150
|
+
|
151
|
+
entries.each do |entry|
|
152
|
+
new_entry = parse_entry(date, entry)
|
153
|
+
items << new_entry if new_entry
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
items
|
158
|
+
end
|
159
|
+
|
160
|
+
Doing::Plugins.register 'capturething', :import, self
|
161
|
+
end
|
162
|
+
end
|
data/rdoc_to_mmd.rb
CHANGED
@@ -3,18 +3,24 @@
|
|
3
3
|
|
4
4
|
input = IO.read('doing.rdoc')
|
5
5
|
|
6
|
+
input.gsub!(/^======= Options/, "###### Options\n\n")
|
6
7
|
input.gsub!(/^===== Options/, "##### Options\n\n")
|
8
|
+
input.gsub!(/^===== Commands/, "### Commands\n")
|
7
9
|
input.gsub!(/^=== Commands/, "## Commands\n")
|
8
|
-
|
10
|
+
|
11
|
+
input.gsub!(/^(?<pre>={4,6}) Command: <tt>(?<cmd>.*?) (?<arg> .*?)?<\/tt>\n(?<after>.*?)$/) do
|
9
12
|
m = Regexp.last_match
|
10
|
-
|
13
|
+
level = m['pre'].length == 6 ? '####' : '###'
|
14
|
+
r = "#{level} #{m['cmd'].sub(/\|(.*?)$/, ' (*or* \1)')}"
|
15
|
+
r += " #{m['arg']}" if m['arg']
|
16
|
+
r += " {##{m['cmd'].gsub(/\|.*?$/, '')}}" if m['pre'].length == 4
|
17
|
+
r += "\n\n"
|
18
|
+
"#{r}**#{m['after']}**{:.description}\n"
|
11
19
|
end
|
12
|
-
|
20
|
+
|
21
|
+
input.gsub!(/(?<=\n)={5,7} (.*?)\n+((.|\n)+?)(?=\n=|$)/s) do
|
13
22
|
m = Regexp.last_match
|
14
|
-
|
15
|
-
r += " #{m[2]}" if m[2]
|
16
|
-
r += " {##{m[1].gsub(/\|.*?$/, '')}}\n\n"
|
17
|
-
"#{r}**#{m[3]}**{:.description}\n"
|
23
|
+
"`#{m[1]}`\n: #{m[2].gsub(/\|/, '\\|')}"
|
18
24
|
end
|
19
25
|
|
20
26
|
input.gsub!(/^=== Global Options/, "## Global Options\n")
|
@@ -28,7 +34,7 @@ input.gsub!(/\n (?=\S)/, ' ')
|
|
28
34
|
input.gsub!(/^([^:`\n#*](.*?))$/, "\\1\n")
|
29
35
|
input.gsub!(/\n{3,}/, "\n\n")
|
30
36
|
input.gsub!(/^(: .*?)\n\n(:.*?)$/, "\\1\n\\2")
|
31
|
-
input.gsub!(/^\[Default Command\] (.*?)$/, '
|
37
|
+
input.gsub!(/^\[Default Command\] (.*?)$/, '> **Default Command:** [`\1`](#\1)')
|
32
38
|
input.gsub!(/\/Users\/ttscoff\/scripts\/editor.sh/, '$EDITOR')
|
33
39
|
input.gsub!(/\/Users\/ttscoff/, '~')
|
34
40
|
puts %(---
|
@@ -155,7 +155,7 @@ class BashCompletions
|
|
155
155
|
end
|
156
156
|
|
157
157
|
def parse_option(option)
|
158
|
-
res = option.match(/(?:-(?<short>\w), )?(?:--(?:\[no-\])?(?<long>
|
158
|
+
res = option.match(/(?:-(?<short>\w), )?(?:--(?:\[no-\])?(?<long>w+)(?:=(?<arg>\w+))?)\s+- (?<desc>.*?)$/)
|
159
159
|
return nil unless res
|
160
160
|
{
|
161
161
|
short: res['short'],
|
@@ -100,7 +100,7 @@ class FishCompletions
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def parse_option(option)
|
103
|
-
res = option.match(/(?:-(?<short>\w), )?(?:--(?:\[no-\])?(?<long>
|
103
|
+
res = option.match(/(?:-(?<short>\w), )?(?:--(?:\[no-\])?(?<long>w+)(?:=(?<arg>\w+))?)\s+- (?<desc>.*?)$/)
|
104
104
|
return nil unless res
|
105
105
|
{
|
106
106
|
short: res['short'],
|
@@ -71,7 +71,7 @@ class ZshCompletions
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def parse_option(option)
|
74
|
-
res = option.match(/(?:-(?<short>\w), )?(?:--(?:\[no-\])?(?<long>
|
74
|
+
res = option.match(/(?:-(?<short>\w), )?(?:--(?:\[no-\])?(?<long>w+)(?:=(?<arg>\w+))?)\s+- (?<desc>.*?)$/)
|
75
75
|
return nil unless res
|
76
76
|
|
77
77
|
{
|
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.
|
4
|
+
version: 2.1.0pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11-
|
11
|
+
date: 2021-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: safe_yaml
|
@@ -166,6 +166,26 @@ dependencies:
|
|
166
166
|
- - ">="
|
167
167
|
- !ruby/object:Gem::Version
|
168
168
|
version: 3.7.3
|
169
|
+
- !ruby/object:Gem::Dependency
|
170
|
+
name: tty-spinner
|
171
|
+
requirement: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - "~>"
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0.9'
|
176
|
+
- - ">="
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: 0.9.3
|
179
|
+
type: :development
|
180
|
+
prerelease: false
|
181
|
+
version_requirements: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - "~>"
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0.9'
|
186
|
+
- - ">="
|
187
|
+
- !ruby/object:Gem::Version
|
188
|
+
version: 0.9.3
|
169
189
|
- !ruby/object:Gem::Dependency
|
170
190
|
name: tty-progressbar
|
171
191
|
requirement: !ruby/object:Gem::Requirement
|
@@ -266,6 +286,46 @@ dependencies:
|
|
266
286
|
- - ">="
|
267
287
|
- !ruby/object:Gem::Version
|
268
288
|
version: 1.2.1
|
289
|
+
- !ruby/object:Gem::Dependency
|
290
|
+
name: tty-link
|
291
|
+
requirement: !ruby/object:Gem::Requirement
|
292
|
+
requirements:
|
293
|
+
- - "~>"
|
294
|
+
- !ruby/object:Gem::Version
|
295
|
+
version: '0.1'
|
296
|
+
- - ">="
|
297
|
+
- !ruby/object:Gem::Version
|
298
|
+
version: 0.1.1
|
299
|
+
type: :runtime
|
300
|
+
prerelease: false
|
301
|
+
version_requirements: !ruby/object:Gem::Requirement
|
302
|
+
requirements:
|
303
|
+
- - "~>"
|
304
|
+
- !ruby/object:Gem::Version
|
305
|
+
version: '0.1'
|
306
|
+
- - ">="
|
307
|
+
- !ruby/object:Gem::Version
|
308
|
+
version: 0.1.1
|
309
|
+
- !ruby/object:Gem::Dependency
|
310
|
+
name: tty-which
|
311
|
+
requirement: !ruby/object:Gem::Requirement
|
312
|
+
requirements:
|
313
|
+
- - "~>"
|
314
|
+
- !ruby/object:Gem::Version
|
315
|
+
version: '0.5'
|
316
|
+
- - ">="
|
317
|
+
- !ruby/object:Gem::Version
|
318
|
+
version: 0.5.0
|
319
|
+
type: :runtime
|
320
|
+
prerelease: false
|
321
|
+
version_requirements: !ruby/object:Gem::Requirement
|
322
|
+
requirements:
|
323
|
+
- - "~>"
|
324
|
+
- !ruby/object:Gem::Version
|
325
|
+
version: '0.5'
|
326
|
+
- - ">="
|
327
|
+
- !ruby/object:Gem::Version
|
328
|
+
version: 0.5.0
|
269
329
|
description: A tool for managing a TaskPaper-like file of recent activites. Perfect
|
270
330
|
for the late-night hacker on too much caffeine to remember what they accomplished
|
271
331
|
at 2 in the morning.
|
@@ -295,7 +355,9 @@ files:
|
|
295
355
|
- doc/Array.html
|
296
356
|
- doc/Doing.html
|
297
357
|
- doc/Doing/Color.html
|
358
|
+
- doc/Doing/Completion.html
|
298
359
|
- doc/Doing/Configuration.html
|
360
|
+
- doc/Doing/Content.html
|
299
361
|
- doc/Doing/Errors.html
|
300
362
|
- doc/Doing/Errors/DoingNoTraceError.html
|
301
363
|
- doc/Doing/Errors/DoingRuntimeError.html
|
@@ -312,8 +374,11 @@ files:
|
|
312
374
|
- doc/Doing/Note.html
|
313
375
|
- doc/Doing/Pager.html
|
314
376
|
- doc/Doing/Plugins.html
|
377
|
+
- doc/Doing/Prompt.html
|
378
|
+
- doc/Doing/Section.html
|
315
379
|
- doc/Doing/Util.html
|
316
380
|
- doc/Doing/WWID.html
|
381
|
+
- doc/Doing/WWIDFile.html
|
317
382
|
- doc/GLI.html
|
318
383
|
- doc/GLI/Commands.html
|
319
384
|
- doc/GLI/Commands/MarkdownDocumentListener.html
|
@@ -360,6 +425,7 @@ files:
|
|
360
425
|
- lib/doing/hash.rb
|
361
426
|
- lib/doing/hooks.rb
|
362
427
|
- lib/doing/item.rb
|
428
|
+
- lib/doing/items.rb
|
363
429
|
- lib/doing/log_adapter.rb
|
364
430
|
- lib/doing/markdown_document_listener.rb
|
365
431
|
- lib/doing/note.rb
|
@@ -375,15 +441,17 @@ files:
|
|
375
441
|
- lib/doing/plugins/import/calendar_import.rb
|
376
442
|
- lib/doing/plugins/import/doing_import.rb
|
377
443
|
- lib/doing/plugins/import/timing_import.rb
|
444
|
+
- lib/doing/prompt.rb
|
445
|
+
- lib/doing/section.rb
|
378
446
|
- lib/doing/string.rb
|
379
447
|
- lib/doing/symbol.rb
|
380
448
|
- lib/doing/time.rb
|
381
449
|
- lib/doing/util.rb
|
382
450
|
- lib/doing/version.rb
|
383
451
|
- lib/doing/wwid.rb
|
384
|
-
- lib/doing/wwidfile.rb
|
385
452
|
- lib/examples/commands/autotag.rb
|
386
453
|
- lib/examples/commands/wiki.rb
|
454
|
+
- lib/examples/plugins/capture_thing_import.rb
|
387
455
|
- lib/examples/plugins/hooks.rb
|
388
456
|
- lib/examples/plugins/say_export.rb
|
389
457
|
- lib/examples/plugins/wiki_export/templates/wiki.css
|
@@ -512,9 +580,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
512
580
|
version: '0'
|
513
581
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
514
582
|
requirements:
|
515
|
-
- - "
|
583
|
+
- - ">"
|
516
584
|
- !ruby/object:Gem::Version
|
517
|
-
version:
|
585
|
+
version: 1.3.1
|
518
586
|
requirements: []
|
519
587
|
rubygems_version: 3.2.16
|
520
588
|
signing_key:
|
data/lib/doing/wwidfile.rb
DELETED
@@ -1,117 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Doing
|
4
|
-
class Items < Array
|
5
|
-
def from(path)
|
6
|
-
return [] unless path
|
7
|
-
path = File.expand_path(path)
|
8
|
-
|
9
|
-
if File.exist?(path) && File.file?(path) && File.stat(path).size.positive?
|
10
|
-
input = IO.read(File.expand_path(input))
|
11
|
-
input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
|
12
|
-
end
|
13
|
-
|
14
|
-
section = 'Uncategorized'
|
15
|
-
lines = input.split(/[\n\r]/)
|
16
|
-
current = 0
|
17
|
-
|
18
|
-
lines.each do |line|
|
19
|
-
next if line =~ /^\s*$/
|
20
|
-
|
21
|
-
if line =~ /^(\S[\S ]+):\s*(@\S+\s*)*$/
|
22
|
-
section = Regexp.last_match(1)
|
23
|
-
@sections << { original: line, title: section }
|
24
|
-
current = 0
|
25
|
-
elsif line =~ /^\s*- (\d{4}-\d\d-\d\d \d\d:\d\d) \| (.*)/
|
26
|
-
date = Regexp.last_match(1).strip
|
27
|
-
title = Regexp.last_match(2).strip
|
28
|
-
item = Item.new(date, title, section)
|
29
|
-
@items.push(item)
|
30
|
-
current += 1
|
31
|
-
elsif current.zero?
|
32
|
-
# if content[section][:items].length - 1 == current
|
33
|
-
@other_content_top.push(line)
|
34
|
-
elsif line =~ /^\S/
|
35
|
-
@other_content_bottom.push(line)
|
36
|
-
else
|
37
|
-
prev_item = @items[current - 1]
|
38
|
-
prev_item.note = Note.new unless prev_item.note
|
39
|
-
|
40
|
-
prev_item.note.add(line)
|
41
|
-
# end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
Hooks.trigger :post_read, self
|
45
|
-
end
|
46
|
-
|
47
|
-
def section_titles
|
48
|
-
@sections.map { |s| s[:title] }
|
49
|
-
end
|
50
|
-
|
51
|
-
##
|
52
|
-
## Adds a section.
|
53
|
-
##
|
54
|
-
## @param title [String] The new section title
|
55
|
-
##
|
56
|
-
def add_section(title)
|
57
|
-
if section_titles.include?(title.cap_first)
|
58
|
-
Doing.logger.debug('Skipped': 'Section already exists')
|
59
|
-
return
|
60
|
-
end
|
61
|
-
|
62
|
-
@sections << { original: "#{title}:", title: title }
|
63
|
-
Doing.logger.info('Added section:', %("#{title.cap_first}"))
|
64
|
-
end
|
65
|
-
|
66
|
-
##
|
67
|
-
## Attempt to match a string with an existing section
|
68
|
-
##
|
69
|
-
## @param frag [String] The user-provided string
|
70
|
-
## @param guessed [Boolean] already guessed and failed
|
71
|
-
##
|
72
|
-
def guess_section(frag, guessed: false, suggest: false)
|
73
|
-
return 'All' if frag =~ /^all$/i
|
74
|
-
frag ||= wwid.config['current_section']
|
75
|
-
|
76
|
-
@sections.each { |sect| return sect[:title].cap_first if frag.downcase == sect[:title].downcase }
|
77
|
-
|
78
|
-
section = false
|
79
|
-
re = frag.split('').join('.*?')
|
80
|
-
sections.each do |sect|
|
81
|
-
next unless sect =~ /#{re}/i
|
82
|
-
|
83
|
-
Doing.logger.debug('Section match:', %(Assuming "#{sect}" from "#{frag}"))
|
84
|
-
section = sect
|
85
|
-
break
|
86
|
-
end
|
87
|
-
|
88
|
-
return section if suggest
|
89
|
-
|
90
|
-
unless section || guessed
|
91
|
-
alt = WWID.guess_view(frag, guessed: true, suggest: true)
|
92
|
-
if alt
|
93
|
-
meant_view = WWID.yn("Did you mean `doing view #{alt}`?", default_response: 'n')
|
94
|
-
raise Errors::InvalidSection, "Run again with `doing view #{alt}`" if meant_view
|
95
|
-
end
|
96
|
-
|
97
|
-
res = WWID.yn("Section #{frag} not found, create it", default_response: 'n')
|
98
|
-
|
99
|
-
if res
|
100
|
-
add_section(frag.cap_first)
|
101
|
-
WWID.write(@doing_file)
|
102
|
-
return frag.cap_first
|
103
|
-
end
|
104
|
-
|
105
|
-
raise Errors::InvalidSection, "Unknown section: #{frag}"
|
106
|
-
end
|
107
|
-
section ? section.cap_first : guessed
|
108
|
-
end
|
109
|
-
|
110
|
-
def section_items(section)
|
111
|
-
section = guess_section(section)
|
112
|
-
return @items if section =~ /all/i
|
113
|
-
|
114
|
-
@items.filter { |i| i.section == section }
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|