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.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/.yardoc/checksums +18 -15
  3. data/.yardoc/object_types +0 -0
  4. data/.yardoc/objects/root.dat +0 -0
  5. data/CHANGELOG.md +36 -1
  6. data/Gemfile.lock +8 -1
  7. data/README.md +7 -1
  8. data/Rakefile +23 -4
  9. data/bin/doing +323 -173
  10. data/doc/Array.html +354 -1
  11. data/doc/Doing/Color.html +104 -92
  12. data/doc/Doing/Completion.html +216 -0
  13. data/doc/Doing/Configuration.html +340 -5
  14. data/doc/Doing/Content.html +229 -0
  15. data/doc/Doing/Errors/DoingNoTraceError.html +1 -1
  16. data/doc/Doing/Errors/DoingRuntimeError.html +1 -1
  17. data/doc/Doing/Errors/DoingStandardError.html +1 -1
  18. data/doc/Doing/Errors/EmptyInput.html +1 -1
  19. data/doc/Doing/Errors/NoResults.html +1 -1
  20. data/doc/Doing/Errors/PluginException.html +1 -1
  21. data/doc/Doing/Errors/UserCancelled.html +1 -1
  22. data/doc/Doing/Errors/WrongCommand.html +1 -1
  23. data/doc/Doing/Errors.html +1 -1
  24. data/doc/Doing/Hooks.html +1 -1
  25. data/doc/Doing/Item.html +337 -49
  26. data/doc/Doing/Items.html +444 -35
  27. data/doc/Doing/LogAdapter.html +139 -51
  28. data/doc/Doing/Note.html +253 -22
  29. data/doc/Doing/Pager.html +74 -36
  30. data/doc/Doing/Plugins.html +1 -1
  31. data/doc/Doing/Prompt.html +674 -0
  32. data/doc/Doing/Section.html +354 -0
  33. data/doc/Doing/Util.html +57 -1
  34. data/doc/Doing/WWID.html +477 -670
  35. data/doc/Doing/WWIDFile.html +398 -0
  36. data/doc/Doing.html +5 -5
  37. data/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
  38. data/doc/GLI/Commands.html +1 -1
  39. data/doc/GLI.html +1 -1
  40. data/doc/Hash.html +97 -1
  41. data/doc/Status.html +37 -3
  42. data/doc/String.html +599 -23
  43. data/doc/Symbol.html +3 -3
  44. data/doc/Time.html +1 -1
  45. data/doc/_index.html +22 -1
  46. data/doc/class_list.html +1 -1
  47. data/doc/file.README.html +8 -2
  48. data/doc/index.html +8 -2
  49. data/doc/method_list.html +453 -173
  50. data/doc/top-level-namespace.html +1 -1
  51. data/doing.gemspec +3 -0
  52. data/doing.rdoc +79 -27
  53. data/example_plugin.rb +5 -5
  54. data/lib/completion/_doing.zsh +42 -42
  55. data/lib/completion/doing.bash +10 -10
  56. data/lib/completion/doing.fish +1 -280
  57. data/lib/doing/array.rb +36 -0
  58. data/lib/doing/colors.rb +70 -66
  59. data/lib/doing/completion/bash_completion.rb +1 -2
  60. data/lib/doing/completion/fish_completion.rb +1 -1
  61. data/lib/doing/completion/zsh_completion.rb +1 -1
  62. data/lib/doing/completion.rb +6 -0
  63. data/lib/doing/configuration.rb +134 -23
  64. data/lib/doing/hash.rb +37 -0
  65. data/lib/doing/item.rb +77 -12
  66. data/lib/doing/items.rb +125 -0
  67. data/lib/doing/log_adapter.rb +58 -4
  68. data/lib/doing/note.rb +53 -1
  69. data/lib/doing/pager.rb +49 -38
  70. data/lib/doing/plugins/export/markdown_export.rb +4 -4
  71. data/lib/doing/plugins/export/template_export.rb +2 -2
  72. data/lib/doing/plugins/import/calendar_import.rb +4 -4
  73. data/lib/doing/plugins/import/doing_import.rb +5 -7
  74. data/lib/doing/plugins/import/timing_import.rb +3 -3
  75. data/lib/doing/prompt.rb +206 -0
  76. data/lib/doing/section.rb +30 -0
  77. data/lib/doing/string.rb +123 -35
  78. data/lib/doing/util.rb +14 -6
  79. data/lib/doing/version.rb +1 -1
  80. data/lib/doing/wwid.rb +307 -614
  81. data/lib/doing.rb +6 -2
  82. data/lib/examples/plugins/capture_thing_import.rb +162 -0
  83. data/rdoc_to_mmd.rb +14 -8
  84. data/scripts/generate_bash_completions.rb +1 -1
  85. data/scripts/generate_fish_completions.rb +1 -1
  86. data/scripts/generate_zsh_completions.rb +1 -1
  87. metadata +73 -5
  88. 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/item'
25
+ require 'doing/section'
26
+ require 'doing/items'
24
27
  require 'doing/note'
25
- require 'doing/wwidfile'
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
- input.gsub!(/(?<=\n)===== (.*?)\n+((.|\n)+?)(?=\n=|$)/s) do
10
+
11
+ input.gsub!(/^(?<pre>={4,6}) Command: <tt>(?<cmd>.*?) (?<arg> .*?)?<\/tt>\n(?<after>.*?)$/) do
9
12
  m = Regexp.last_match
10
- "`#{m[1]}`\n: #{m[2].gsub(/\|/, '\\|')}"
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
- input.gsub!(/^==== Command: <tt>(.*?) ( .*?)?<\/tt>\n(.*?)$/) do
20
+
21
+ input.gsub!(/(?<=\n)={5,7} (.*?)\n+((.|\n)+?)(?=\n=|$)/s) do
13
22
  m = Regexp.last_match
14
- r = "### #{m[1].sub(/\|(.*?)$/, ' (*or* \1)')}"
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\] (.*?)$/, '## Default Command: [`\1`](#\1)')
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>[\w_]+)(?:=(?<arg>\w+))?)\s+- (?<desc>.*?)$/)
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>[\w_]+)(?:=(?<arg>\w+))?)\s+- (?<desc>.*?)$/)
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>[\w_]+)(?:=(?<arg>\w+))?)\s+- (?<desc>.*?)$/)
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.0.22
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-23 00:00:00.000000000 Z
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: '0'
585
+ version: 1.3.1
518
586
  requirements: []
519
587
  rubygems_version: 3.2.16
520
588
  signing_key:
@@ -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