doing 2.0.25 → 2.1.0pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) 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 +28 -0
  6. data/Gemfile.lock +8 -1
  7. data/README.md +1 -1
  8. data/Rakefile +23 -4
  9. data/bin/doing +205 -127
  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 +40 -12
  53. data/example_plugin.rb +3 -3
  54. data/lib/completion/_doing.zsh +1 -1
  55. data/lib/completion/doing.bash +8 -8
  56. data/lib/completion/doing.fish +1 -1
  57. data/lib/doing/array.rb +36 -0
  58. data/lib/doing/colors.rb +70 -66
  59. data/lib/doing/completion.rb +6 -0
  60. data/lib/doing/configuration.rb +69 -28
  61. data/lib/doing/hash.rb +37 -0
  62. data/lib/doing/item.rb +77 -12
  63. data/lib/doing/items.rb +125 -0
  64. data/lib/doing/log_adapter.rb +55 -3
  65. data/lib/doing/note.rb +53 -1
  66. data/lib/doing/pager.rb +49 -38
  67. data/lib/doing/plugins/export/markdown_export.rb +4 -4
  68. data/lib/doing/plugins/export/template_export.rb +2 -2
  69. data/lib/doing/plugins/import/calendar_import.rb +4 -4
  70. data/lib/doing/plugins/import/doing_import.rb +5 -7
  71. data/lib/doing/plugins/import/timing_import.rb +3 -3
  72. data/lib/doing/prompt.rb +206 -0
  73. data/lib/doing/section.rb +30 -0
  74. data/lib/doing/string.rb +103 -27
  75. data/lib/doing/util.rb +14 -6
  76. data/lib/doing/version.rb +1 -1
  77. data/lib/doing/wwid.rb +306 -621
  78. data/lib/doing.rb +6 -2
  79. data/lib/examples/plugins/capture_thing_import.rb +162 -0
  80. metadata +73 -5
  81. data/lib/doing/wwidfile.rb +0 -117
@@ -102,7 +102,7 @@
102
102
  </div>
103
103
 
104
104
  <div id="footer">
105
- Generated on Thu Nov 18 16:39:11 2021 by
105
+ Generated on Sat Nov 27 10:06:03 2021 by
106
106
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
107
107
  0.9.26 (ruby-3.0.1).
108
108
  </div>
data/doing.gemspec CHANGED
@@ -31,10 +31,13 @@ spec = Gem::Specification.new do |s|
31
31
  s.add_development_dependency 'redcarpet', '~> 3.5', '>= 3.5.1'
32
32
  s.add_development_dependency 'github-markup', '~> 4.0', '>= 4.0.0'
33
33
  s.add_development_dependency 'parallel_tests', '~> 3.7', '>= 3.7.3'
34
+ s.add_development_dependency 'tty-spinner', '~> 0.9', '>= 0.9.3'
34
35
  s.add_runtime_dependency('tty-progressbar', '~> 0.18', '>= 0.18.2')
35
36
  s.add_runtime_dependency('gli', '~> 2.19', '>= 2.19.2')
36
37
  s.add_runtime_dependency('haml','~>5.0.0', '>= 5.0.0')
37
38
  s.add_runtime_dependency('chronic','~> 0.10', '>= 0.10.2')
38
39
  s.add_runtime_dependency('deep_merge', '~> 1.2', '>= 1.2.1')
40
+ s.add_runtime_dependency('tty-link', '~> 0.1', '>= 0.1.1')
41
+ s.add_runtime_dependency('tty-which', '~> 0.5', '>= 0.5.0')
39
42
  # s.add_runtime_dependency('amatch', '~> 0.4', '>= 0.4.0')
40
43
  end
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.0.25
8
+ v2.1.0pre
9
9
 
10
10
  === Global Options
11
11
  === --config_file arg
@@ -42,6 +42,11 @@ Show this message
42
42
 
43
43
 
44
44
 
45
+ === --no
46
+ Answer all yes/no menus with no
47
+
48
+
49
+
45
50
  === --[no-]notes
46
51
  Output notes if included in the template
47
52
 
@@ -72,6 +77,11 @@ Exclude auto tags and default tags
72
77
 
73
78
 
74
79
 
80
+ === --yes
81
+ Answer all yes/no menus with yes
82
+
83
+
84
+
75
85
  === Commands
76
86
  ==== Command: <tt>add_section SECTION_NAME</tt>
77
87
  Add a new section to the "doing" file
@@ -414,14 +424,14 @@ Open config file in editor
414
424
 
415
425
 
416
426
  ======= Options
417
- ======= -a APP_NAME
427
+ ======= -a|--app APP_NAME
418
428
 
419
429
  Application to use
420
430
 
421
431
  [Default Value] None
422
432
 
423
433
 
424
- ======= -b BUNDLE_ID
434
+ ======= -b|--bundle_id BUNDLE_ID
425
435
 
426
436
  Application bundle id to use
427
437
 
@@ -435,7 +445,7 @@ Editor to use
435
445
  [Default Value] None
436
446
 
437
447
 
438
- ======= -x
448
+ ======= -x|--[no-]default
439
449
  Use the config_editor_app defined in ~/.config/doing/config.yml (config_editor_app not set)
440
450
 
441
451
 
@@ -453,10 +463,21 @@ Format for output (json|yaml|raw)
453
463
  [Must Match] (?-mix:^(?:y(?:aml)?|j(?:son)?|r(?:aw)?)$)
454
464
 
455
465
 
466
+ ====== Command: <tt>list </tt>
467
+ List configuration paths, including .doingrc files in the current and parent directories
468
+
469
+ Config files are listed in order of precedence (if there are multiple configs detected).
470
+ Values defined in the top item in the list will override values in configutations below it.
456
471
  ====== Command: <tt>set </tt>
457
472
  Set a key's value in the config file
458
473
 
459
474
 
475
+ ======= Options
476
+ ======= -r|--remove
477
+ Delete specified key
478
+
479
+
480
+
460
481
  ====== Command: <tt>undo </tt>
461
482
  Undo the last change to a config file
462
483
 
@@ -479,9 +500,9 @@ Set finish date to specific date/time (natural langauge parsed, e.g. --at=1:30pm
479
500
  [Default Value] None
480
501
 
481
502
 
482
- ===== -b|--back DATE_STRING
503
+ ===== -b|--back|--started DATE_STRING
483
504
 
484
- Backdate start date by interval [4pm|20m|2h|yesterday noon]
505
+ Backdate start date by interval or set to time [4pm|20m|2h|"yesterday noon"]
485
506
 
486
507
  [Default Value] None
487
508
 
@@ -734,7 +755,7 @@ List commands one per line, to assist with shell completion
734
755
  ==== Command: <tt>import PATH</tt>
735
756
  Import entries from an external source
736
757
 
737
- Imports entries from other sources. Available plugins: calendar, doing, timing
758
+ Imports entries from other sources. Available plugins: calendar, capturething, doing, timing
738
759
  ===== Options
739
760
  ===== --after DATE_STRING
740
761
 
@@ -797,7 +818,7 @@ Tag all imported entries
797
818
 
798
819
  ===== --type TYPE
799
820
 
800
- Import type (calendar|doing|timing)
821
+ Import type (calendar|capturething|doing|timing)
801
822
 
802
823
  [Default Value] doing
803
824
 
@@ -1110,9 +1131,9 @@ A parenthetical at the end of the entry will be converted to a note.
1110
1131
 
1111
1132
  Run with no argument to create a new entry using vim.
1112
1133
  ===== Options
1113
- ===== -b|--back DATE_STRING
1134
+ ===== -b|--back|--started DATE_STRING
1114
1135
 
1115
- Backdate start time [4pm|20m|2h|yesterday noon]
1136
+ Backdate start time [4pm|20m|2h|"yesterday noon"]
1116
1137
 
1117
1138
  [Default Value] None
1118
1139
 
@@ -1199,6 +1220,13 @@ Open with app bundle id
1199
1220
  [Default Value] None
1200
1221
 
1201
1222
 
1223
+ ===== -e|--editor COMMAND
1224
+
1225
+ Open with editor command (e.g. vim, mate)
1226
+
1227
+ [Default Value] None
1228
+
1229
+
1202
1230
  ==== Command: <tt>plugins </tt>
1203
1231
  List installed plugins
1204
1232
 
@@ -1808,7 +1836,7 @@ Output HTML, CSS, and Markdown (ERB) templates for customization
1808
1836
  Templates are printed to STDOUT for piping to a file.
1809
1837
  Save them and use them in the configuration file under export_templates.
1810
1838
  ===== Options
1811
- ===== -c
1839
+ ===== -c|--[no-]column
1812
1840
  List in single column for completion
1813
1841
 
1814
1842
 
@@ -1874,7 +1902,7 @@ Show time totals at the end of output
1874
1902
 
1875
1903
 
1876
1904
  ==== Command: <tt>undo </tt>
1877
- Undo the last change to the doing_file
1905
+ Undo the last change to the Doing file
1878
1906
 
1879
1907
 
1880
1908
  ===== Options
data/example_plugin.rb CHANGED
@@ -136,9 +136,9 @@ module Doing
136
136
  # or :map to generate output.
137
137
  i = items[-1]
138
138
 
139
- # Format the item. Items are a hash with 4 keys: date,
140
- # title, section (parent section), and note. Start
141
- # time is in item.date. The wwid object has some
139
+ # Format the item. Items are an object with 4 methods:
140
+ # date, title, section (parent section), and note.
141
+ # Start time is in item.date. The wwid object has some
142
142
  # methods for calculation and formatting, including
143
143
  # wwid.item.end_date to convert the @done timestamp to
144
144
  # an end date.
@@ -48,7 +48,7 @@ function _doing() {
48
48
  'template:Output HTML'
49
49
  'test:Test Stuff'
50
50
  'today:List entries from today'
51
- 'undo:Undo the last change to the doing_file'
51
+ 'undo:Undo the last change to the Doing file'
52
52
  'view:Display a user-created view'
53
53
  'views:List available custom views'
54
54
  'wiki:Output a tag wiki'
@@ -81,9 +81,9 @@ _doing_config() {
81
81
  _doing_done() {
82
82
 
83
83
  if [[ "$token" == --* ]]; then
84
- COMPREPLY=( $( compgen -W '--archive --at --back --date --editor --note --remove --section --took --unfinished' -- $token ) )
84
+ COMPREPLY=( $( compgen -W '--archive --at --started --date --editor --note --remove --section --took --unfinished' -- $token ) )
85
85
  elif [[ "$token" == -* ]]; then
86
- COMPREPLY=( $( compgen -W '-a -b -e -n -r -s -t -u --archive --at --back --date --editor --note --remove --section --took --unfinished' -- $token ) )
86
+ COMPREPLY=( $( compgen -W '-a -e -n -r -s -t -u --archive --at --started --date --editor --note --remove --section --took --unfinished' -- $token ) )
87
87
 
88
88
  fi
89
89
  }
@@ -181,9 +181,9 @@ _doing_note() {
181
181
  _doing_now() {
182
182
 
183
183
  if [[ "$token" == --* ]]; then
184
- COMPREPLY=( $( compgen -W '--back --editor --finish_last --note --section' -- $token ) )
184
+ COMPREPLY=( $( compgen -W '--started --editor --finish_last --note --section' -- $token ) )
185
185
  elif [[ "$token" == -* ]]; then
186
- COMPREPLY=( $( compgen -W '-b -e -f -n -s --back --editor --finish_last --note --section' -- $token ) )
186
+ COMPREPLY=( $( compgen -W '-e -f -n -s --started --editor --finish_last --note --section' -- $token ) )
187
187
 
188
188
  fi
189
189
  }
@@ -201,9 +201,9 @@ _doing_on() {
201
201
  _doing_open() {
202
202
 
203
203
  if [[ "$token" == --* ]]; then
204
- COMPREPLY=( $( compgen -W '--app --bundle_id' -- $token ) )
204
+ COMPREPLY=( $( compgen -W '--app --bundle_id --editor' -- $token ) )
205
205
  elif [[ "$token" == -* ]]; then
206
- COMPREPLY=( $( compgen -W '-a -b --app --bundle_id' -- $token ) )
206
+ COMPREPLY=( $( compgen -W '-a -b -e --app --bundle_id --editor' -- $token ) )
207
207
 
208
208
  fi
209
209
  }
@@ -321,9 +321,9 @@ _doing_tag() {
321
321
  _doing_template() {
322
322
 
323
323
  if [[ "$token" == --* ]]; then
324
- COMPREPLY=( $( compgen -W '--list' -- $token ) )
324
+ COMPREPLY=( $( compgen -W '--column --list' -- $token ) )
325
325
  elif [[ "$token" == -* ]]; then
326
- COMPREPLY=( $( compgen -W '-l --list' -- $token ) )
326
+ COMPREPLY=( $( compgen -W '-c -l --column --list' -- $token ) )
327
327
 
328
328
  fi
329
329
  }
@@ -91,7 +91,7 @@ complete -xc doing -n '__fish_doing_needs_command' -a 'tag' -d Add\ tag\(s\)\ to
91
91
  complete -xc doing -n '__fish_doing_needs_command' -a 'template' -d Output\ HTML
92
92
  complete -xc doing -n '__fish_doing_needs_command' -a 'test' -d Test\ Stuff
93
93
  complete -xc doing -n '__fish_doing_needs_command' -a 'today' -d List\ entries\ from\ today
94
- complete -xc doing -n '__fish_doing_needs_command' -a 'undo' -d Undo\ the\ last\ change\ to\ the\ doing_file
94
+ complete -xc doing -n '__fish_doing_needs_command' -a 'undo' -d Undo\ the\ last\ change\ to\ the\ Doing\ file
95
95
  complete -xc doing -n '__fish_doing_needs_command' -a 'view' -d Display\ a\ user-created\ view
96
96
  complete -xc doing -n '__fish_doing_needs_command' -a 'views' -d List\ available\ custom\ views
97
97
  complete -xc doing -n '__fish_doing_needs_command' -a 'wiki' -d Output\ a\ tag\ wiki
data/lib/doing/array.rb CHANGED
@@ -5,17 +5,53 @@ module Doing
5
5
  ## Array helpers
6
6
  ##
7
7
  class ::Array
8
+ # Convert strings to @tags
9
+ #
10
+ # @example `['one', '@two', 'three'].to_tags`
11
+ # @example `=> ['@one', '@two', '@three']`
12
+ # @return [Array] Array of @tags
13
+ #
8
14
  def to_tags
9
15
  map { |t| t.sub(/^@?/, '@') }
10
16
  end
11
17
 
18
+ def to_tags!
19
+ replace to_tags
20
+ end
21
+
22
+ ##
23
+ ## Hightlight @tags in string for console output
24
+ ##
25
+ ## @param color [String] the color to highlight
26
+ ## with
27
+ ##
28
+ ## @return [String] string with @tags highlighted
29
+ ##
12
30
  def highlight_tags(color = 'cyan')
13
31
  tag_color = Doing::Color.send(color)
14
32
  to_tags.map { |t| "#{tag_color}#{t}" }
15
33
  end
16
34
 
35
+ ##
36
+ ## Tag array for logging
37
+ ##
38
+ ## @return [String] Highlighted tag array joined with comma
39
+ ##
17
40
  def log_tags
18
41
  highlight_tags.join(', ')
19
42
  end
43
+
44
+ ##
45
+ ## Convert array to nested hash, setting last key to value
46
+ ##
47
+ ## @param value The value to set
48
+ ##
49
+ def nested_hash(value)
50
+ raise StandardError, 'Value can not be nil' if value.nil?
51
+
52
+ hsh = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
53
+ hsh.dig(*self[0..-2])[self.fetch(-1)] = value
54
+ hsh
55
+ end
20
56
  end
21
57
  end
data/lib/doing/colors.rb CHANGED
@@ -1,64 +1,65 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Cribbed from <https://github.com/flori/term-ansicolor>
2
4
  module Doing
5
+ # Terminal color functions
3
6
  module Color
4
-
5
7
  # :stopdoc:
6
8
  ATTRIBUTES = [
7
- [ :clear , 0 ], # String#clear is already used to empty string in Ruby 1.9
8
- [ :reset , 0 ], # synonym for :clear
9
- [ :bold , 1 ],
10
- [ :dark , 2 ],
11
- [ :italic , 3 ], # not widely implemented
12
- [ :underline , 4 ],
13
- [ :underscore , 4 ], # synonym for :underline
14
- [ :blink , 5 ],
15
- [ :rapid_blink , 6 ], # not widely implemented
16
- [ :negative , 7 ], # no reverse because of String#reverse
17
- [ :concealed , 8 ],
18
- [ :strikethrough , 9 ], # not widely implemented
19
- [ :black , 30 ],
20
- [ :red , 31 ],
21
- [ :green , 32 ],
22
- [ :yellow , 33 ],
23
- [ :blue , 34 ],
24
- [ :magenta , 35 ],
25
- [ :cyan , 36 ],
26
- [ :white , 37 ],
27
- [ :bgblack , 40 ],
28
- [ :bgred , 41 ],
29
- [ :bggreen , 42 ],
30
- [ :bgyellow , 43 ],
31
- [ :bgblue , 44 ],
32
- [ :bgmagenta , 45 ],
33
- [ :bgcyan , 46 ],
34
- [ :bgwhite , 47 ],
35
- [ :boldblack , 90 ], # High intensity, aixterm (works in OS X)
36
- [ :boldred , 91 ],
37
- [ :boldgreen , 92 ],
38
- [ :boldyellow , 93 ],
39
- [ :boldblue , 94 ],
40
- [ :boldmagenta , 95 ],
41
- [ :boldcyan , 96 ],
42
- [ :boldwhite , 97 ],
43
- [ :boldbgblack , 100 ], # High intensity background, aixterm (works in OS X)
44
- [ :boldbgred , 101 ],
45
- [ :boldbggreen , 102 ],
46
- [ :boldbgyellow , 103 ],
47
- [ :boldbgblue , 104 ],
48
- [ :boldbgmagenta , 105 ],
49
- [ :boldbgcyan , 106 ],
50
- [ :boldbgwhite , 107 ],
51
- [ :softpurple , '0;35;40'],
52
- [ :hotpants , '7;34;40'],
53
- [ :knightrider , '7;30;40'],
54
- [ :flamingo , '7;31;47'],
55
- [ :yeller , '1;37;43'],
56
- [ :whiteboard , '1;30;47'],
57
- [ :default , '0;39' ]
58
- ]
9
+ [:clear, 0], # String#clear is already used to empty string in Ruby 1.9
10
+ [:reset, 0], # synonym for :clear
11
+ [:bold, 1],
12
+ [:dark, 2],
13
+ [:italic, 3], # not widely implemented
14
+ [:underline, 4],
15
+ [:underscore, 4], # synonym for :underline
16
+ [:blink, 5],
17
+ [:rapid_blink, 6], # not widely implemented
18
+ [:negative, 7], # no reverse because of String#reverse
19
+ [:concealed, 8],
20
+ [:strikethrough, 9], # not widely implemented
21
+ [:black, 30],
22
+ [:red, 31],
23
+ [:green, 32],
24
+ [:yellow, 33],
25
+ [:blue, 34],
26
+ [:magenta, 35],
27
+ [:cyan, 36],
28
+ [:white, 37],
29
+ [:bgblack, 40],
30
+ [:bgred, 41],
31
+ [:bggreen, 42],
32
+ [:bgyellow, 43],
33
+ [:bgblue, 44],
34
+ [:bgmagenta, 45],
35
+ [:bgcyan, 46],
36
+ [:bgwhite, 47],
37
+ [:boldblack, 90], # High intensity, aixterm (works in OS X)
38
+ [:boldred, 91],
39
+ [:boldgreen, 92],
40
+ [:boldyellow, 93],
41
+ [:boldblue, 94],
42
+ [:boldmagenta, 95],
43
+ [:boldcyan, 96],
44
+ [:boldwhite, 97],
45
+ [:boldbgblack, 100], # High intensity background, aixterm (works in OS X)
46
+ [:boldbgred, 101],
47
+ [:boldbggreen, 102],
48
+ [:boldbgyellow, 103],
49
+ [:boldbgblue, 104],
50
+ [:boldbgmagenta, 105],
51
+ [:boldbgcyan, 106],
52
+ [:boldbgwhite, 107],
53
+ [:softpurple, '0;35;40'],
54
+ [:hotpants, '7;34;40'],
55
+ [:knightrider, '7;30;40'],
56
+ [:flamingo, '7;31;47'],
57
+ [:yeller, '1;37;43'],
58
+ [:whiteboard, '1;30;47'],
59
+ [:default, '0;39']
60
+ ].map(&:freeze).freeze
59
61
 
60
62
  ATTRIBUTE_NAMES = ATTRIBUTES.transpose.first
61
- # :startdoc:
62
63
 
63
64
  # Returns true if Doing::Color supports the +feature+.
64
65
  #
@@ -72,19 +73,23 @@ module Doing
72
73
  !String.instance_methods(false).map(&:to_sym).include?(:clear)
73
74
  end
74
75
  end
75
- # Returns true, if the coloring function of this module
76
- # is switched on, false otherwise.
77
- def self.coloring?
78
- @coloring
79
- end
80
76
 
81
- # Turns the coloring on or off globally, so you can easily do
82
- # this for example:
83
- # Doing::Color::coloring = STDOUT.isatty
84
- def self.coloring=(val)
85
- @coloring = val
77
+ class << self
78
+ # Returns true, if the coloring function of this module
79
+ # is switched on, false otherwise.
80
+ def coloring?
81
+ @coloring
82
+ end
83
+
84
+ # Turns the coloring on or off globally, so you can easily do
85
+ # this for example:
86
+ # Doing::Color::coloring = STDOUT.isatty
87
+ attr_writer :coloring
88
+
89
+ def coloring
90
+ @coloring ||= true
91
+ end
86
92
  end
87
- self.coloring = true
88
93
 
89
94
  ATTRIBUTES.each do |c, v|
90
95
  eval <<-EOT
@@ -133,4 +138,3 @@ module Doing
133
138
  extend self
134
139
  end
135
140
  end
136
-
@@ -12,6 +12,12 @@ module Doing
12
12
  # Completion script generator
13
13
  module Completion
14
14
  class << self
15
+ # Generate a completion script and output to file or
16
+ # stdout
17
+ #
18
+ # @param type [String] shell to generate for (zsh|bash|fish)
19
+ # @param file [String] Path to save to, or 'stdout'
20
+ #
15
21
  def generate_completion(type: 'zsh', file: 'stdout')
16
22
 
17
23
  generator = case type.to_s
@@ -99,6 +99,10 @@ module Doing
99
99
  @config_file ||= default_config_file
100
100
  end
101
101
 
102
+ def config_file=(file)
103
+ @config_file = file
104
+ end
105
+
102
106
  def config_dir
103
107
  @config_dir ||= File.join(Util.user_home, '.config', 'doing')
104
108
  # @config_dir ||= Util.user_home
@@ -116,20 +120,20 @@ module Doing
116
120
  File.join(config_dir, 'config.yml')
117
121
  end
118
122
 
119
- def config_file=(file)
120
- @config_file = file
121
- end
122
-
123
-
124
123
  def additional_configs
125
124
  @additional_configs ||= find_local_config
126
125
  end
127
126
 
127
+ ##
128
+ ## Present a menu if there are multiple configs found
129
+ ##
130
+ ## @return [String] file path
131
+ ##
128
132
  def choose_config
129
133
  if @additional_configs.count.positive?
130
134
  choices = [@config_file]
131
135
  choices.concat(@additional_configs)
132
- res = Doing::WWID.new.choose_from(choices.uniq.sort.reverse, sorted: false, prompt: 'Local configs found, select which to update > ')
136
+ res = Doing::Prompt.choose_from(choices.uniq.sort.reverse, sorted: false, prompt: 'Local configs found, select which to update > ')
133
137
 
134
138
  raise UserCancelled, 'Cancelled' unless res
135
139
 
@@ -139,6 +143,16 @@ module Doing
139
143
  end
140
144
  end
141
145
 
146
+ ##
147
+ ## Resolve a fuzzy-matched key path
148
+ ##
149
+ ## @param keypath [String] A dot-separated key
150
+ ## path, e.g.
151
+ ## "plugins.plugin_path". Will also
152
+ ## work with "plug.path" (fuzzy
153
+ ## matched, first match wins)
154
+ ## @return [Array] ordered array of resolved keys
155
+ ##
142
156
  def resolve_key_path(keypath)
143
157
  cfg = @settings
144
158
  real_path = []
@@ -166,12 +180,22 @@ module Doing
166
180
  real_path
167
181
  end
168
182
 
183
+ ##
184
+ ## Get the value for a fuzzy-matched key path
185
+ ##
186
+ ## @param keypath [String] A dot-separated key
187
+ ## path, e.g.
188
+ ## "plugins.plugin_path". Will also
189
+ ## work with "plug.path" (fuzzy
190
+ ## matched, first match wins)
191
+ ## @return [Hash] Config value
192
+ ##
169
193
  def value_for_key(keypath = '')
170
194
  cfg = @settings
171
195
  real_path = ['config']
172
196
  unless keypath =~ /^[.*]?$/
173
197
  real_path = resolve_key_path(keypath)
174
- return nil unless real_path && real_path.count.positive?
198
+ return nil unless real_path&.count&.positive?
175
199
 
176
200
  cfg = cfg.dig(*real_path)
177
201
  end
@@ -188,6 +212,9 @@ module Doing
188
212
  Util.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys)
189
213
  end
190
214
 
215
+ ##
216
+ ## Method for transitioning from ~/.doingrc to ~/.config/doing/config.yml
217
+ ##
191
218
  def update_deprecated_config
192
219
  # return # Until further notice
193
220
  return if File.exist?(default_config_file)
@@ -199,22 +226,23 @@ module Doing
199
226
  Doing.logger.log_now(:warn, 'Deprecated:', "main config file location has changed to #{config_file}")
200
227
  res = wwid.yn("Move #{old_file} to new location, preserving settings?", default_response: true)
201
228
 
202
- if res
203
- if File.exist?(default_config_file)
204
- res = wwid.yn("#{default_config_file} already exists, overwrite it?", default_response: false)
229
+ return unless res
205
230
 
206
- unless res
207
- @config_file = old_file
208
- return
209
- end
210
- end
231
+ if File.exist?(default_config_file)
232
+ res = wwid.yn("#{default_config_file} already exists, overwrite it?", default_response: false)
211
233
 
212
- FileUtils.mv old_file, default_config_file, force: true
213
- Doing.logger.log_now(:warn, 'Config:', "Config file moved to #{default_config_file}")
214
- Doing.logger.log_now(:warn, 'Config:', %(If ~/.config/doing/config.yml exists in the future, it will be considered a local
215
- config and its values will override the default configuration.))
216
- Process.exit 0
234
+ unless res
235
+ @config_file = old_file
236
+ return
237
+ end
217
238
  end
239
+
240
+ FileUtils.mv old_file, default_config_file, force: true
241
+ Doing.logger.log_now(:warn, 'Config:', "Config file moved to #{default_config_file}")
242
+ Doing.logger.log_now(:warn, 'Config:', %(If ~/.doingrc exists in the future,
243
+ it will be considered a local config and its values will override the
244
+ default configuration.))
245
+ Process.exit 0
218
246
  end
219
247
 
220
248
  ##
@@ -261,8 +289,23 @@ module Doing
261
289
  config
262
290
  end
263
291
 
292
+ # @private
293
+ def inspect
294
+ %(<Doing::Configuration #{@settings.hash}>)
295
+ end
296
+
297
+ # @private
298
+ def to_s
299
+ YAML.dump(@settings)
300
+ end
301
+
264
302
  private
265
303
 
304
+ ##
305
+ ## Test for deprecated config keys
306
+ ##
307
+ ## @param config The configuration
308
+ ##
266
309
  def find_deprecations(config)
267
310
  deprecated = false
268
311
  if config.key?('editor')
@@ -276,14 +319,16 @@ module Doing
276
319
  deprecated = true
277
320
  config['editors']['config'] = config['config_editor_app']
278
321
  config.delete('config_editor_app')
279
- Doing.logger.debug('Deprecated:', "config key 'config_editor_app' is now 'editors->config', please update your config.")
322
+ Doing.logger.debug('Deprecated:',
323
+ "config key 'config_editor_app' is now 'editors->config', please update your config.")
280
324
  end
281
325
 
282
326
  if config.key?('editor_app') && !config['editors']['doing_file']
283
327
  deprecated = true
284
328
  config['editors']['doing_file'] = config['editor_app']
285
329
  config.delete('editor_app')
286
- Doing.logger.debug('Deprecated:', "config key 'editor_app' is now 'editors->doing_file', please update your config.")
330
+ Doing.logger.debug('Deprecated:',
331
+ "config key 'editor_app' is now 'editors->doing_file', please update your config.")
287
332
  end
288
333
 
289
334
  Doing.logger.warn('Deprecated:', 'outdated keys found, please run `doing config --update`.') if deprecated
@@ -327,7 +372,7 @@ module Doing
327
372
  ##
328
373
  def read_config
329
374
  unless File.exist?(config_file)
330
- Doing.logger.info('Config:', 'Config file doesn\'t exist, using default configuration' )
375
+ Doing.logger.info('Config:', 'Config file doesn\'t exist, using default configuration')
331
376
  return {}.deep_merge(DEFAULTS)
332
377
  end
333
378
 
@@ -372,11 +417,7 @@ module Doing
372
417
  end
373
418
 
374
419
  def load_plugins(add_dir = nil)
375
- begin
376
- FileUtils.mkdir_p(add_dir) if add_dir && !File.exist?(add_dir)
377
- rescue
378
- nil
379
- end
420
+ FileUtils.mkdir_p(add_dir) if add_dir && !File.exist?(add_dir)
380
421
 
381
422
  Plugins.load_plugins(add_dir)
382
423
  end