doing 2.1.15 → 2.1.19

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/.yardoc/checksums +10 -10
  3. data/.yardoc/object_types +0 -0
  4. data/.yardoc/objects/root.dat +0 -0
  5. data/CHANGELOG.md +109 -51
  6. data/Gemfile.lock +1 -1
  7. data/README.md +1 -1
  8. data/bin/doing +131 -45
  9. data/docs/doc/Array.html +1 -1
  10. data/docs/doc/BooleanTermParser/Clause.html +1 -1
  11. data/docs/doc/BooleanTermParser/Operator.html +1 -1
  12. data/docs/doc/BooleanTermParser/Query.html +1 -1
  13. data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
  14. data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
  15. data/docs/doc/BooleanTermParser.html +1 -1
  16. data/docs/doc/Doing/Color.html +6 -2
  17. data/docs/doc/Doing/Completion.html +1 -1
  18. data/docs/doc/Doing/Configuration.html +4 -3
  19. data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
  20. data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
  21. data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
  22. data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
  23. data/docs/doc/Doing/Errors/NoResults.html +1 -1
  24. data/docs/doc/Doing/Errors/PluginException.html +1 -1
  25. data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
  26. data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
  27. data/docs/doc/Doing/Errors.html +1 -1
  28. data/docs/doc/Doing/Hooks.html +1 -1
  29. data/docs/doc/Doing/Item.html +119 -1
  30. data/docs/doc/Doing/Items.html +1 -1
  31. data/docs/doc/Doing/LogAdapter.html +1 -1
  32. data/docs/doc/Doing/Note.html +1 -1
  33. data/docs/doc/Doing/Pager.html +1 -1
  34. data/docs/doc/Doing/Plugins.html +1 -1
  35. data/docs/doc/Doing/Prompt.html +69 -1
  36. data/docs/doc/Doing/Section.html +1 -1
  37. data/docs/doc/Doing/TemplateString.html +2 -2
  38. data/docs/doc/Doing/Util/Backup.html +1 -1
  39. data/docs/doc/Doing/Util.html +1 -1
  40. data/docs/doc/Doing/WWID.html +37 -3
  41. data/docs/doc/Doing.html +2 -2
  42. data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
  43. data/docs/doc/GLI/Commands.html +1 -1
  44. data/docs/doc/GLI.html +1 -1
  45. data/docs/doc/Hash.html +1 -1
  46. data/docs/doc/Numeric.html +1 -1
  47. data/docs/doc/PhraseParser/Operator.html +1 -1
  48. data/docs/doc/PhraseParser/PhraseClause.html +1 -1
  49. data/docs/doc/PhraseParser/Query.html +1 -1
  50. data/docs/doc/PhraseParser/QueryParser.html +1 -1
  51. data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
  52. data/docs/doc/PhraseParser/TermClause.html +1 -1
  53. data/docs/doc/PhraseParser.html +1 -1
  54. data/docs/doc/Status.html +1 -1
  55. data/docs/doc/String.html +228 -1
  56. data/docs/doc/Symbol.html +1 -1
  57. data/docs/doc/Time.html +1 -1
  58. data/docs/doc/_index.html +1 -1
  59. data/docs/doc/file.README.html +2 -2
  60. data/docs/doc/index.html +2 -2
  61. data/docs/doc/method_list.html +254 -182
  62. data/docs/doc/top-level-namespace.html +1 -1
  63. data/doing.rdoc +34 -4
  64. data/lib/completion/_doing.zsh +7 -7
  65. data/lib/completion/doing.bash +10 -10
  66. data/lib/completion/doing.fish +6 -1
  67. data/lib/doing/colors.rb +4 -0
  68. data/lib/doing/configuration.rb +2 -1
  69. data/lib/doing/item.rb +51 -0
  70. data/lib/doing/log_adapter.rb +2 -2
  71. data/lib/doing/plugins/export/template_export.rb +2 -0
  72. data/lib/doing/prompt.rb +52 -0
  73. data/lib/doing/string.rb +43 -0
  74. data/lib/doing/string_chronify.rb +28 -0
  75. data/lib/doing/template_string.rb +1 -1
  76. data/lib/doing/version.rb +1 -1
  77. data/lib/doing/wwid.rb +54 -23
  78. data/lib/doing.rb +5 -4
  79. metadata +2 -2
data/lib/doing/wwid.rb CHANGED
@@ -187,6 +187,8 @@ module Doing
187
187
  iso_rx = /\d{4}-\d\d-\d\d \d\d:\d\d/
188
188
  date_rx = /^(?:\s*- )?(?<date>.*?) \| (?=\S)/
189
189
 
190
+ raise EmptyInput, 'No content' if title.sub(/^.*?\| */, '').strip.empty?
191
+
190
192
  title.expand_date_tags(@config['date_tags'])
191
193
 
192
194
  if title =~ date_rx
@@ -796,17 +798,18 @@ module Doing
796
798
  end
797
799
 
798
800
  def delete_items(items, force: false)
799
- res = force ? true : Prompt.yn("Delete #{items.size} #{items.size == 1 ? 'item' : 'items'}?", default_response: 'y')
800
- if res
801
- items.each do |i|
802
- deleted = @content.delete_item(i, single: items.count == 1)
803
- Hooks.trigger :post_entry_removed, self, deleted
804
- end
805
- write(@doing_file)
806
- end
801
+ items.slice(0, 5).each { |i| puts i.to_pretty } unless force
802
+ puts softpurple("+ #{items.size - 5} additional #{'item'.to_p(items.size - 5)}") if items.size > 5 && !force
803
+
804
+ res = force ? true : Prompt.yn("Delete #{items.size} #{'item'.to_p(items.size)}?", default_response: 'y')
805
+ return unless res
806
+
807
+ items.each { |i| Hooks.trigger :post_entry_removed, self, @content.delete_item(i, single: items.count == 1) }
808
+ write(@doing_file)
807
809
  end
808
810
 
809
811
  def edit_items(items)
812
+ items.sort_by! { |i| i.date }
810
813
  editable_items = []
811
814
 
812
815
  items.each do |i|
@@ -815,16 +818,16 @@ module Doing
815
818
  editable += "\n#{old_note}" unless old_note.nil?
816
819
  editable_items << editable
817
820
  end
818
- divider = "\n-----------\n"
821
+ divider = "-----------"
819
822
  notice =<<~EONOTICE
820
823
  # - You may delete entries, but leave all divider lines (---) in place.
821
824
  # - Start and @done dates replaced with a time string (yesterday 3pm) will
822
825
  # be parsed automatically. Do not delete the pipe (|) between start date
823
826
  # and entry title.
824
827
  EONOTICE
825
- input = "#{editable_items.map(&:strip).join(divider)}\n\n#{notice}"
828
+ input = "#{editable_items.map(&:strip).join("\n#{divider}\n")}\n\n#{notice}"
826
829
 
827
- new_items = fork_editor(input).split(/#{divider}/)
830
+ new_items = fork_editor(input).split(/^#{divider}/).map(&:strip)
828
831
 
829
832
  new_items.each_with_index do |new_item, i|
830
833
  input_lines = new_item.split(/[\n\r]+/).delete_if(&:ignore?)
@@ -833,7 +836,7 @@ module Doing
833
836
  if first_line.nil? || first_line =~ /^#{divider.strip}$/ || first_line.strip.empty?
834
837
  deleted = @content.delete_item(items[i], single: new_items.count == 1)
835
838
  Hooks.trigger :post_entry_removed, self, deleted
836
- Doing.logger.count(:deleted)
839
+ Doing.logger.info('Deleted:', deleted.title)
837
840
  else
838
841
  date, title, note = format_input(new_item)
839
842
 
@@ -961,8 +964,14 @@ module Doing
961
964
  type = action =~ /^add/ ? 'add' : 'remove'
962
965
  raise InvalidArgument, "'add tag' and 'remove tag' can not be used together" if opt[:tag]
963
966
 
964
- print "#{yellow("Tag to #{type}: ")}#{reset}"
965
- tag = $stdin.gets
967
+ tags = type == 'add' ? all_tags(@content) : all_tags(items)
968
+
969
+ puts "#{yellow}Separate multiple tags with spaces, hit tab to complete known tags#{type == 'add' ? ', include values with tag(value)' : ''}"
970
+ puts "#{boldgreen}Available tags: #{boldwhite}#{tags.sort.map(&:add_at).join(', ')}" if type == 'remove'
971
+ tag = Prompt.read_line(prompt: "Tags to #{type}", completions: tags)
972
+
973
+ # print "#{yellow("Tag to #{type}: ")}#{reset}"
974
+ # tag = $stdin.gets
966
975
  next if tag =~ /^ *$/
967
976
 
968
977
  opt[:tag] = tag.strip.sub(/^@/, '')
@@ -984,8 +993,9 @@ module Doing
984
993
  opt[:output] = output_format.strip
985
994
  res = opt[:force] ? false : Prompt.yn('Save to file?', default_response: 'n')
986
995
  if res
987
- print "#{yellow('File path/name: ')}#{reset}"
988
- filename = $stdin.gets.strip
996
+ # print "#{yellow('File path/name: ')}#{reset}"
997
+ # filename = $stdin.gets.strip
998
+ filename = Prompt.read_line(prompt: 'File path/name')
989
999
  next if filename.empty?
990
1000
 
991
1001
  opt[:save_to] = filename
@@ -1093,10 +1103,10 @@ module Doing
1093
1103
  i
1094
1104
  end
1095
1105
 
1096
- @content = Items.new
1097
- @content.concat(items)
1098
- @content.add_section(Section.new('Export'), log: false)
1099
- options = { section: 'Export' }
1106
+ export_items = Items.new
1107
+ export_items.concat(items)
1108
+ export_items.add_section(Section.new('Export'), log: false)
1109
+ options = { section: 'All' }
1100
1110
 
1101
1111
  if opt[:output] =~ /doing/
1102
1112
  options[:output] = 'template'
@@ -1106,7 +1116,7 @@ module Doing
1106
1116
  options[:template] = opt[:template] || nil
1107
1117
  end
1108
1118
 
1109
- output = list_section(options) # hooked
1119
+ output = list_section(options, items: export_items) # hooked
1110
1120
 
1111
1121
  if opt[:save_to]
1112
1122
  file = File.expand_path(opt[:save_to])
@@ -1183,6 +1193,19 @@ module Doing
1183
1193
 
1184
1194
  raise NoResults, 'no items matched your search' if items.empty?
1185
1195
 
1196
+ if opt[:tags].empty? && !opt[:autotag]
1197
+ completions = opt[:remove] ? all_tags(items) : all_tags(@content)
1198
+ if opt[:remove]
1199
+ puts "#{yellow}Available tags: #{boldwhite}#{completions.map(&:add_at).join(', ')}"
1200
+ else
1201
+ puts "#{yellow}Use tab to complete known tags"
1202
+ end
1203
+ opt[:tags] = Doing::Prompt.read_line(prompt: "Enter tag(s) to #{opt[:remove] ? 'remove' : 'add'}",
1204
+ completions: completions,
1205
+ default_response: '').to_tags
1206
+ raise UserCancelled, 'No tags provided' if opt[:tags].empty?
1207
+ end
1208
+
1186
1209
  items.each do |item|
1187
1210
  added = []
1188
1211
  removed = []
@@ -1617,9 +1640,9 @@ module Doing
1617
1640
  opt[:menu] = !opt[:force]
1618
1641
  opt[:query] = '' # opt[:search]
1619
1642
  opt[:multiple] = true
1620
- selected = Prompt.choose_from_items(items, include_section: opt[:section] =~ /^all$/i, **opt)
1643
+ selected = Prompt.choose_from_items(items.reverse, include_section: opt[:section] =~ /^all$/i, **opt)
1621
1644
 
1622
- raise NoResults, 'no items selected' if selected.empty?
1645
+ raise NoResults, 'no items selected' if selected.nil? || selected.empty?
1623
1646
 
1624
1647
  act_on(selected, opt)
1625
1648
  return
@@ -1627,6 +1650,7 @@ module Doing
1627
1650
 
1628
1651
  opt[:output] ||= 'template'
1629
1652
  opt[:wrap_width] ||= @config['templates']['default']['wrap_width'] || 0
1653
+
1630
1654
  output(items, title, is_single, opt)
1631
1655
  end
1632
1656
 
@@ -2126,6 +2150,13 @@ EOS
2126
2150
  false
2127
2151
  end
2128
2152
 
2153
+ ##
2154
+ ## Load configuration files and updated the @config
2155
+ ## attribute with a Doing::Configuration object
2156
+ ##
2157
+ ## @param filename [String] (optional) path to
2158
+ ## alternative config file
2159
+ ##
2129
2160
  def configure(filename = nil)
2130
2161
  if filename
2131
2162
  Doing.config_with(filename, { ignore_local: true })
data/lib/doing.rb CHANGED
@@ -10,6 +10,11 @@ require 'tempfile'
10
10
  require 'zlib'
11
11
  require 'base64'
12
12
  require 'plist'
13
+ require 'readline'
14
+ require 'haml'
15
+ require 'json'
16
+ require 'logger'
17
+ require 'safe_yaml/load'
13
18
 
14
19
  require 'chronic'
15
20
  require 'tty-link'
@@ -17,10 +22,6 @@ require 'tty-which'
17
22
  require 'tty-markdown'
18
23
  require 'tty-reader'
19
24
  require 'tty-screen'
20
- require 'haml'
21
- require 'json'
22
- require 'logger'
23
- require 'safe_yaml/load'
24
25
 
25
26
  require_relative 'doing/hash'
26
27
  require_relative 'doing/colors'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: doing
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.15
4
+ version: 2.1.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-17 00:00:00.000000000 Z
11
+ date: 2022-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: safe_yaml