diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c81bf37..fa3deaf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +### 2.1.87 + +2024-12-14 15:27 + +#### FIXED + +- Trying to fix runtime slowness + ### 2.1.86 2024-03-26 10:57 diff --git a/Gemfile.lock b/Gemfile.lock index a4b75f65..8f1aea71 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - doing (2.1.86) + doing (2.1.87) chronic (~> 0.10, >= 0.10.2) deep_merge (~> 1.2, >= 1.2.1) gli (~> 2.20, >= 2.20.1) @@ -22,12 +22,12 @@ GEM chronic (0.10.2) deep_merge (1.2.2) github-markup (4.0.2) - gli (2.21.1) + gli (2.22.0) haml (5.0.4) temple (>= 0.8.0) tilt - kramdown (2.4.0) - rexml + kramdown (2.5.1) + rexml (>= 3.3.9) parallel (1.24.0) parallel_tests (3.13.0) parallel @@ -39,23 +39,21 @@ GEM rake (13.0.6) rdoc (6.3.4.1) redcarpet (3.6.0) - rexml (3.3.6) - strscan - rouge (4.2.0) + rexml (3.3.9) + rouge (4.5.1) safe_yaml (1.0.5) strings (0.2.1) strings-ansi (~> 0.2) unicode-display_width (>= 1.5, < 3.0) unicode_utils (~> 1.4) strings-ansi (0.2.0) - strscan (3.1.0) temple (0.10.3) test-unit (3.4.9) power_assert - tilt (2.3.0) + tilt (2.4.0) tty-color (0.6.0) tty-cursor (0.7.1) - tty-link (0.1.1) + tty-link (0.2.0) tty-markdown (0.7.2) kramdown (>= 1.16.2, < 3.0) pastel (~> 0.8) @@ -63,7 +61,7 @@ GEM strings (~> 0.2.0) tty-color (~> 0.5) tty-screen (~> 0.8) - tty-progressbar (0.18.2) + tty-progressbar (0.18.3) strings-ansi (~> 0.2) tty-cursor (~> 0.7) tty-screen (~> 0.8) @@ -76,7 +74,7 @@ GEM tty-spinner (0.9.3) tty-cursor (~> 0.7) tty-which (0.5.0) - unicode-display_width (2.5.0) + unicode-display_width (2.6.0) unicode_utils (1.4.0) wisper (2.0.1) yard (0.9.36) diff --git a/README.md b/README.md index 6ce3f892..9412a76d 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ _If you're one of the rare people like me who find this useful, feel free to -The current version of `doing` is 2.1.85. +The current version of `doing` is 2.1.86. Find all of the documentation in the [doing wiki][wiki]. diff --git a/docs/doc/Array.html b/docs/doc/Array.html index 24f6f480..f2112dff 100644 --- a/docs/doc/Array.html +++ b/docs/doc/Array.html @@ -263,25 +263,7 @@

- - - - - -
-
-
-
-31
-32
-33
-
-
# File 'lib/doing/array/array.rb', line 31
-
-def cap_first
-  map(&:cap_first)
-end
-
+
@@ -321,25 +303,7 @@

-

- - - - -
-
-
-
-59
-60
-61
-
-
# File 'lib/doing/good.rb', line 59
-
-def good?
-  !nil? && !empty?
-end
-
+
@@ -378,35 +342,7 @@

-

- - - - -
-
-
-
-17
-18
-19
-20
-21
-22
-23
-24
-
-
# File 'lib/doing/array/array.rb', line 17
-
-def utf8
-  c = self.class
-  if String.method_defined? :force_encoding
-    replace c.new(map(&:utf8))
-  else
-    self
-  end
-end
-
+ @@ -414,7 +350,7 @@

diff --git a/docs/doc/BooleanTermParser.html b/docs/doc/BooleanTermParser.html index 06c9c52c..97af0505 100644 --- a/docs/doc/BooleanTermParser.html +++ b/docs/doc/BooleanTermParser.html @@ -105,7 +105,7 @@

Defined Under Namespace

diff --git a/docs/doc/BooleanTermParser/Clause.html b/docs/doc/BooleanTermParser/Clause.html index 0e2e756a..7e0d95da 100644 --- a/docs/doc/BooleanTermParser/Clause.html +++ b/docs/doc/BooleanTermParser/Clause.html @@ -221,27 +221,7 @@

-
- - - - -
-
-
-
-42
-43
-44
-45
-
-
# File 'lib/doing/boolean_term_parser.rb', line 42
-
-def initialize(operator, term)
-  self.operator = Operator.symbol(operator)
-  self.term = term
-end
-
+ @@ -270,25 +250,7 @@

-
- - - - -
-
-
-
-40
-41
-42
-
-
# File 'lib/doing/boolean_term_parser.rb', line 40
-
-def operator
-  @operator
-end
-
+ @@ -312,25 +274,7 @@

-
- - - - -
-
-
-
-40
-41
-42
-
-
# File 'lib/doing/boolean_term_parser.rb', line 40
-
-def term
-  @term
-end
-
+ @@ -339,7 +283,7 @@

diff --git a/docs/doc/BooleanTermParser/Operator.html b/docs/doc/BooleanTermParser/Operator.html index 970145d4..4d222223 100644 --- a/docs/doc/BooleanTermParser/Operator.html +++ b/docs/doc/BooleanTermParser/Operator.html @@ -154,43 +154,7 @@

-

- - - - -
-
-
-
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-
-
# File 'lib/doing/boolean_term_parser.rb', line 25
-
-def self.symbol(str)
-  case str
-  when '+'
-    :must
-  when '-'
-    :must_not
-  when nil
-    :should
-  else
-    raise "Unknown operator: #{str}"
-  end
-end
-
+ @@ -198,7 +162,7 @@

diff --git a/docs/doc/BooleanTermParser/Query.html b/docs/doc/BooleanTermParser/Query.html index 1a59f7a8..bd1ae553 100644 --- a/docs/doc/BooleanTermParser/Query.html +++ b/docs/doc/BooleanTermParser/Query.html @@ -291,31 +291,7 @@

-
- - - - -
-
-
-
-51
-52
-53
-54
-55
-56
-
-
# File 'lib/doing/boolean_term_parser.rb', line 51
-
-def initialize(clauses)
-  grouped = clauses.chunk { |c| c.operator }.to_h
-  self.should_terms = grouped.fetch(:should, []).map(&:term)
-  self.must_not_terms = grouped.fetch(:must_not, []).map(&:term)
-  self.must_terms = grouped.fetch(:must, []).map(&:term)
-end
-
+ @@ -344,25 +320,7 @@

-
- - - - -
-
-
-
-49
-50
-51
-
-
# File 'lib/doing/boolean_term_parser.rb', line 49
-
-def must_not_terms
-  @must_not_terms
-end
-
+ @@ -386,25 +344,7 @@

-
- - - - -
-
-
-
-49
-50
-51
-
-
# File 'lib/doing/boolean_term_parser.rb', line 49
-
-def must_terms
-  @must_terms
-end
-
+ @@ -428,25 +368,7 @@

-
- - - - -
-
-
-
-49
-50
-51
-
-
# File 'lib/doing/boolean_term_parser.rb', line 49
-
-def should_terms
-  @should_terms
-end
-
+ @@ -465,25 +387,7 @@

-

- - - - -
-
-
-
-82
-83
-84
-
-
# File 'lib/doing/boolean_term_parser.rb', line 82
-
-def match(term)
-  term
-end
-
+
@@ -495,65 +399,7 @@

-

- - - - -
-
-
-
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-
-
# File 'lib/doing/boolean_term_parser.rb', line 58
-
-def to_elasticsearch
-  query = {}
-
-  if should_terms.any?
-    query[:should] = should_terms.map do |term|
-      match(term)
-    end
-  end
-
-  if must_terms.any?
-    query[:must] = must_terms.map do |term|
-      match(term)
-    end
-  end
-
-  if must_not_terms.any?
-    query[:must_not] = must_not_terms.map do |term|
-      match(term)
-    end
-  end
-
-  query
-end
-
+
@@ -561,7 +407,7 @@

diff --git a/docs/doc/BooleanTermParser/QueryParser.html b/docs/doc/BooleanTermParser/QueryParser.html index 9b3e811c..f56411bb 100644 --- a/docs/doc/BooleanTermParser/QueryParser.html +++ b/docs/doc/BooleanTermParser/QueryParser.html @@ -125,7 +125,7 @@

Overview

diff --git a/docs/doc/BooleanTermParser/QueryTransformer.html b/docs/doc/BooleanTermParser/QueryTransformer.html index f576d646..a5afefef 100644 --- a/docs/doc/BooleanTermParser/QueryTransformer.html +++ b/docs/doc/BooleanTermParser/QueryTransformer.html @@ -114,7 +114,7 @@ diff --git a/docs/doc/Doing.html b/docs/doc/Doing.html index 813522fb..f341b05f 100644 --- a/docs/doc/Doing.html +++ b/docs/doc/Doing.html @@ -122,7 +122,7 @@

VERSION =
-
'2.1.86'
+
'2.1.87'
@@ -138,7 +138,7 @@

diff --git a/docs/doc/Doing/ArrayCleanup.html b/docs/doc/Doing/ArrayCleanup.html index d1af8049..bb3127e0 100644 --- a/docs/doc/Doing/ArrayCleanup.html +++ b/docs/doc/Doing/ArrayCleanup.html @@ -234,25 +234,7 @@

- - - - - -
-
-
-
-9
-10
-11
-
-
# File 'lib/doing/array/cleanup.rb', line 9
-
-def remove_bad
-  compact.map { |x| x.is_a?(String) ? x.strip : x }.select(&:good?)
-end
-
+
@@ -264,25 +246,7 @@

-

- - - - -
-
-
-
-13
-14
-15
-
-
# File 'lib/doing/array/cleanup.rb', line 13
-
-def remove_bad!
-  replace remove_empty
-end
-
+

@@ -322,25 +286,7 @@

-

- - - - -
-
-
-
-23
-24
-25
-
-
# File 'lib/doing/array/cleanup.rb', line 23
-
-def remove_empty
-  compact.map { |x| x.is_a?(String) ? x.strip : x }.reject { |x| x.is_a?(String) ? x.empty? : false }
-end
-
+
@@ -352,25 +298,7 @@

-

- - - - -
-
-
-
-27
-28
-29
-
-
# File 'lib/doing/array/cleanup.rb', line 27
-
-def remove_empty!
-  replace remove_empty
-end
-
+
@@ -378,7 +306,7 @@

diff --git a/docs/doc/Doing/ArrayNestedHash.html b/docs/doc/Doing/ArrayNestedHash.html index 9161ab1b..0ce26fc4 100644 --- a/docs/doc/Doing/ArrayNestedHash.html +++ b/docs/doc/Doing/ArrayNestedHash.html @@ -180,29 +180,7 @@

- - - - - -
-
-
-
-11
-12
-13
-14
-15
-
-
# File 'lib/doing/array/nested_hash.rb', line 11
-
-def nested_hash(value = nil)
-  hsh = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
-  hsh.dig(*self[0..-2])[fetch(-1)] = value
-  hsh
-end
-
+ @@ -210,7 +188,7 @@

diff --git a/docs/doc/Doing/ArrayTags.html b/docs/doc/Doing/ArrayTags.html index f6711649..e72de0b2 100644 --- a/docs/doc/Doing/ArrayTags.html +++ b/docs/doc/Doing/ArrayTags.html @@ -267,25 +267,7 @@

- - - - - -
-
-
-
-37
-38
-39
-
-
# File 'lib/doing/array/tags.rb', line 37
-
-def highlight_tags(color = 'cyan')
-  to_tags.map { |t| Doing::Color.send(color.to_sym, t) }
-end
-
+
@@ -324,25 +306,7 @@

-

- - - - -
-
-
-
-46
-47
-48
-
-
# File 'lib/doing/array/tags.rb', line 46
-
-def log_tags(color = 'cyan')
-  highlight_tags(color).join(', ')
-end
-
+
@@ -392,25 +356,7 @@

Convert an array of tags to str -

- - - - -
-
-
-
-15
-16
-17
-
-
# File 'lib/doing/array/tags.rb', line 15
-
-def tags_to_array
-  map(&:remove_at).map(&:strip)
-end
-
+
@@ -460,25 +406,7 @@

Convert an array of strings wit -

- - - - -
-
-
-
-25
-26
-27
-
-
# File 'lib/doing/array/tags.rb', line 25
-
-def to_tags
-  map(&:add_at)
-end
-
+
@@ -486,7 +414,7 @@

Convert an array of strings wit

diff --git a/docs/doc/Doing/ByDayExport.html b/docs/doc/Doing/ByDayExport.html index a552f933..8558bc26 100644 --- a/docs/doc/Doing/ByDayExport.html +++ b/docs/doc/Doing/ByDayExport.html @@ -176,115 +176,7 @@

-

- - - - -
-
-
-
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-
-
# File 'lib/doing/plugins/export/byday.rb', line 18
-
-def self.render(wwid, items, variables: {})
-  return if items.nil?
-
-  days = {}
-
-  items.each do |item|
-    date = item.date.strftime('%Y-%m-%d')
-    days[date] ||= []
-    days[date].push(item)
-  end
-
-  totals = {}
-  total = 0
-
-  days.each do |day, day_items|
-    day_items.each do |item|
-      totals[day] ||= 0
-      duration = item.interval || 0
-      totals[day] += duration
-      total += duration
-    end
-  end
-  width = wwid.config['plugins']['byday']['item_width'].to_i || 60
-  divider = "{wd}+{xk}#{'-' *10}{wd}+{xk}#{'-' * width}{wd}+{xk}#{'-' * 8}{wd}+{x}"
-  out = []
-  out << divider
-  out << "{wd}|{xm}date      {wd}|{xbw}item#{' ' * (width - 4)}{wd}|{xy}duration{wd}|{x}"
-  out << divider
-  days.each do |day, day_items|
-    first = day_items.slice!(0, 1)[0]
-    interval = wwid.get_interval(first, formatted: true) || '00:00:00'
-    title = first.title.tag('done', remove: true).trunc(width - 2).ljust(width)
-    out << "{wd}|{xm}#{day}{wd}|{xbw}#{title}{wd}|{xy}#{interval}{wd}|{x}"
-    day_items.each do |item|
-      interval = wwid.get_interval(item, formatted: true) || '00:00:00'
-      title = item.title.tag('done', remove: true).trunc(width - 2).ljust(width)
-      out << "{wd}|          |{xbw}#{title}{wd}|{xy}#{interval}{wd}|{x}"
-    end
-    day_total = "Total: #{totals[day].time_string(format: :clock)}"
-    out << divider
-    out << "{wd}|{xg}#{day_total.rjust(width + 20)}{wd}|{x}"
-    out << divider
-  end
-  all_total = "Grand Total: #{total.time_string(format: :clock)}"
-  out << "{wd}|{xrb}#{all_total.rjust(width + 20)}{wd}|{x}"
-  out << divider
-  Doing::Color.template(out.join("\n"))
-end
-
+
@@ -296,35 +188,7 @@

-

- - - - -
-
-
-
-9
-10
-11
-12
-13
-14
-15
-16
-
-
# File 'lib/doing/plugins/export/byday.rb', line 9
-
-def self.settings
-  {
-    trigger: 'byday',
-    config: {
-      'item_width' => 60
-    }
-  }
-end
-
+
@@ -332,7 +196,7 @@

diff --git a/docs/doc/Doing/CSVExport.html b/docs/doc/Doing/CSVExport.html index 475222c8..2cb888c0 100644 --- a/docs/doc/Doing/CSVExport.html +++ b/docs/doc/Doing/CSVExport.html @@ -224,37 +224,7 @@

-

- - - - -
-
-
-
-36
-37
-38
-39
-40
-41
-42
-43
-44
-
-
# File 'lib/doing/plugins/export/csv_export.rb', line 36
-
-def self.format_note(note)
-  out = ''
-  if note
-    arr = note.map(&:strip).delete_if { |e| e =~ /^\s*$/ }
-    out = arr.join("\n") unless arr.empty?
-  end
-
-  out
-end
-
+
@@ -266,49 +236,7 @@

-

- - - - -
-
-
-
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-
-
# File 'lib/doing/plugins/export/csv_export.rb', line 20
-
-def self.render(wwid, items, variables: {})
-  return if items.nil?
-
-  opt = variables[:options]
-
-  output = [CSV.generate_line(%w[start end title note timer section])]
-  items.each do |i|
-    note = format_note(i.note)
-    end_date = i.end_date
-    interval = end_date && opt[:times] ? wwid.get_interval(i, formatted: false) : 0
-    output.push(CSV.generate_line([i.date, end_date, i.title, note, interval, i.section]))
-  end
-  Doing.logger.debug('CSV Export:', "#{items.count} items output to CSV")
-  output.join('')
-end
-
+
@@ -320,29 +248,7 @@

-

- - - - -
-
-
-
-14
-15
-16
-17
-18
-
-
# File 'lib/doing/plugins/export/csv_export.rb', line 14
-
-def self.settings
-  {
-    trigger: 'csv'
-  }
-end
-
+
@@ -350,7 +256,7 @@

diff --git a/docs/doc/Doing/CalendarImport.html b/docs/doc/Doing/CalendarImport.html index 6ececb37..79a6a5fc 100644 --- a/docs/doc/Doing/CalendarImport.html +++ b/docs/doc/Doing/CalendarImport.html @@ -202,167 +202,7 @@

-

- - - - -
-
-
-
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-
-
# File 'lib/doing/plugins/import/calendar_import.rb', line 22
-
-def self.import(wwid, _path, options: {})
-  limit_start = options[:start].to_i
-  limit_end = options[:end].to_i
-
-  section = options[:section] || Doing.setting('current_section')
-  options[:no_overlap] ||= false
-  options[:autotag] ||= Doing.auto_tag
-
-  wwid.content.add_section(section) unless wwid.content.section?(section)
-
-  tags = options[:tag] ? options[:tag].split(/[ ,]+/).map { |t| t.sub(/^@?/, '') } : []
-  prefix = options[:prefix] || '[Calendar.app]'
-
-  script = File.join(File.dirname(__FILE__), 'cal_to_json.scpt')
-  res = `/usr/bin/osascript "#{script}" #{limit_start} #{limit_end}`.strip
-  data = JSON.parse(res)
-
-  new_items = []
-  data.each do |entry|
-    # Only process entries with a start and end date
-    next unless entry.key?('start') && entry.key?('end')
-
-    # Round down seconds and convert UTC to local time
-    start_time = Time.parse(entry['start']).getlocal
-    end_time = Time.parse(entry['end']).getlocal
-    next unless start_time && end_time
-
-    title = "#{prefix} "
-    title += entry['name']
-    tags.each do |tag|
-      if title =~ /\b#{tag}\b/i
-        title.sub!(/\b#{tag}\b/i, "@#{tag}")
-      else
-        title += " @#{tag}"
-      end
-    end
-    title = wwid.autotag(title) if options[:autotag]
-    title += " @done(#{end_time.strftime('%Y-%m-%d %H:%M')})"
-    title.gsub!(/ +/, ' ')
-    title.strip!
-    new_entry = Item.new(start_time, title, section)
-    new_entry.note = entry['notes'].split(/\n/).map(&:chomp) if entry.key?('notes')
-
-    is_match = true
-
-    if options[:search]
-      is_match = new_entry.search(options[:search], case_type: options[:date], negate: options[:not])
-    end
-
-    if is_match && options[:date_filter]
-      is_match = start_time > options[:date_filter][0] && start_time < options[:date_filter][1]
-      is_match = options[:not] ? !is_match : is_match
-    end
-
-    new_items.push(new_entry) if is_match
-  end
-  total = new_items.count
-
-  new_items = wwid.filter_items(new_items, opt: options)
-  filtered = total - new_items.count
-  Doing.logger.debug('Skipped:' , %(#{filtered} items that didn't match filter criteria)) if filtered.positive?
-
-  new_items = wwid.dedup(new_items, no_overlap: options[:no_overlap])
-  dups = filtered - new_items.count
-  Doing.logger.info(%(Skipped #{dups} items with overlapping times)) if dups.positive?
-
-  new_items.map { |item| Hooks.trigger :pre_entry_add, self, item }
-
-  wwid.content.concat(new_items)
-
-  new_items.map { |item| Hooks.trigger :post_entry_added, self, item }
-
-  Doing.logger.info(%(Imported #{new_items.count} items to #{section}))
-end
-
+
@@ -374,29 +214,7 @@

-

- - - - -
-
-
-
-16
-17
-18
-19
-20
-
-
# File 'lib/doing/plugins/import/calendar_import.rb', line 16
-
-def self.settings
-  {
-    trigger: 'i?cal(?:endar)?'
-  }
-end
-
+
@@ -404,7 +222,7 @@

diff --git a/docs/doc/Doing/Change.html b/docs/doc/Doing/Change.html index 87a55555..6494a0d9 100644 --- a/docs/doc/Doing/Change.html +++ b/docs/doc/Doing/Change.html @@ -447,33 +447,7 @@

-
- - - - -
-
-
-
-12
-13
-14
-15
-16
-17
-18
-
-
# File 'lib/doing/changelog/change.rb', line 12
-
-def initialize(version, content, prefix: false, only: %i[changed new improved fixed])
-  @version = Version.new(version)
-  @content = content
-  @prefix = prefix
-  @only = only
-  parse_entries
-end
-
+ @@ -502,25 +476,7 @@

-
- - - - -
-
-
-
-8
-9
-10
-
-
# File 'lib/doing/changelog/change.rb', line 8
-
-def change_date
-  @change_date
-end
-
+ @@ -544,25 +500,7 @@

-
- - - - -
-
-
-
-6
-7
-8
-
-
# File 'lib/doing/changelog/change.rb', line 6
-
-def content
-  @content
-end
-
+ @@ -586,25 +524,7 @@

-
- - - - -
-
-
-
-8
-9
-10
-
-
# File 'lib/doing/changelog/change.rb', line 8
-
-def entries
-  @entries
-end
-
+ @@ -647,25 +567,7 @@

- - - - - -
-
-
-
-10
-11
-12
-
-
# File 'lib/doing/changelog/change.rb', line 10
-
-def prefix=(value)
-  @prefix = value
-end
-
+ @@ -689,25 +591,7 @@

-
- - - - -
-
-
-
-6
-7
-8
-
-
# File 'lib/doing/changelog/change.rb', line 6
-
-def version
-  @version
-end
-
+ @@ -726,41 +610,7 @@

-

- - - - -
-
-
-
-94
-95
-96
-97
-98
-99
-100
-101
-102
-103
-104
-
-
# File 'lib/doing/changelog/change.rb', line 94
-
-def changes_only
-  out = []
-
-  split_items.each do |type, members|
-    next unless @only.include?(type)
-
-    out << members.map(&:to_s).join("\n")
-  end
-
-  out.join("\n")
-end
-
+
@@ -772,43 +622,7 @@

-

- - - - -
-
-
-
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-
-
# File 'lib/doing/changelog/change.rb', line 20
-
-def parse_entries
-  date = @content.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/)
-  @change_date = Time.parse(date[0]) if date
-
-  @entries = []
-  types = @content.scan(/(?<=\n|\A)#### (CHANGED|NEW|IMPROVED|FIXED)(.*?)(?=\n####|\Z)/m)
-  types.each do |type|
-    type[1].scan(/\s*- +(.*?)$/).each do |entry|
-      @entries << Entry.new(entry[0].strip, type[0], prefix: @prefix)
-    end
-  end
-end
-
+
@@ -820,69 +634,7 @@

-

- - - - -
-
-
-
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-
-
# File 'lib/doing/changelog/change.rb', line 33
-
-def search_entries(search_string)
-  case_type = :ignore
-
-  matches = []
-
-  if search_string.rx?
-    matches = @entries.select { |e| e.string =~ search_string.to_rx(distance: 2, case_type: case_type) }
-  else
-    query = search_string.gsub(/(-)?--/, '\1]]').to_phrase_query
-
-    if query[:must].nil? && query[:must_not].nil?
-      query[:must] = query[:should]
-      query[:should] = []
-    end
-
-    @entries.each do |entry|
-      m = no_searches?(entry.string, query[:must_not])
-      m &&= all_searches?(entry.string, query[:must])
-      m &&= any_searches?(entry.string, query[:should])
-      matches << entry if m
-    end
-  end
-
-  @entries = matches.count.positive? ? matches : nil
-end
-
+
@@ -894,47 +646,7 @@

-

- - - - -
-
-
-
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-
-
# File 'lib/doing/changelog/change.rb', line 63
-
-def split_items
-  items = { changed: [], new: [], improved: [], fixed: [], other: [] }
-
-  @entries.each do |e|
-    type = e.type.downcase.to_sym
-    if items.key?(type)
-      items[type] << e
-    else
-      items[:other] << e
-    end
-  end
-
-  items
-end
-
+
@@ -946,25 +658,7 @@

-

- - - - -
-
-
-
-59
-60
-61
-
-
# File 'lib/doing/changelog/change.rb', line 59
-
-def to_h
-  { version: @version, content: @content }
-end
-
+
@@ -976,49 +670,7 @@

-

- - - - -
-
-
-
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-
-
# File 'lib/doing/changelog/change.rb', line 78
-
-def to_s
-  date = @change_date.nil? ? '' : " _(#{@change_date.strftime('%F')})_"
-  out = ["### __#{@version}__#{date}"]
-
-  split_items.each do |type, members|
-    next unless @only.include?(type)
-
-    if members.count.positive?
-      out << "#### #{type.to_s.capitalize}"
-      out << members.map(&:to_s).join("\n")
-    end
-  end
-
-  out.join("\n\n")
-end
-
+
@@ -1026,7 +678,7 @@

diff --git a/docs/doc/Doing/Changes.html b/docs/doc/Doing/Changes.html index 0c9c9f98..a9618290 100644 --- a/docs/doc/Doing/Changes.html +++ b/docs/doc/Doing/Changes.html @@ -323,43 +323,7 @@

-
- - - - -
-
-
-
-9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-
-
# File 'lib/doing/changelog/changes.rb', line 9
-
-def initialize(lookup: nil, search: nil, changes: false, sort: :desc, prefix: false, only: %i[changed new improved fixed])
-  @changes_only = changes
-  @prefix = prefix
-  @only = only
-  changelog = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'CHANGELOG.md'))
-  raise 'Error locating changelog' unless File.exist?(changelog)
-
-  @content = IO.read(changelog)
-  parse_changes(lookup, search)
-
-  @changes.reverse! if sort == :asc
-end
-
+ @@ -388,25 +352,7 @@

-
- - - - -
-
-
-
-6
-7
-8
-
-
# File 'lib/doing/changelog/changes.rb', line 6
-
-def changes
-  @changes
-end
-
+ @@ -449,25 +395,7 @@

- - - - - -
-
-
-
-7
-8
-9
-
-
# File 'lib/doing/changelog/changes.rb', line 7
-
-def changes_only=(value)
-  @changes_only = value
-end
-
+ @@ -486,41 +414,7 @@

-

- - - - -
-
-
-
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-
-
# File 'lib/doing/changelog/changes.rb', line 34
-
-def interactive
-  Doing::Prompt.choose_from(versions,
-                            prompt: 'Select a version to see its changelog',
-                            sorted: false,
-                            fzf_args: [
-                              %(--preview='doing changes --render -l {1}'),
-                              '--disabled',
-                              '--height=50',
-                              '--preview-window="right,70%"'
-                            ])
-end
-
+
@@ -532,33 +426,7 @@

-

- - - - -
-
-
-
-22
-23
-24
-25
-26
-27
-28
-
-
# File 'lib/doing/changelog/changes.rb', line 22
-
-def latest
-  if @changes_only
-    @changes[0].changes_only.force_encoding('utf-8')
-  else
-    @changes[0].to_s.force_encoding('utf-8')
-  end
-end
-
+
@@ -570,33 +438,7 @@

-

- - - - -
-
-
-
-46
-47
-48
-49
-50
-51
-52
-
-
# File 'lib/doing/changelog/changes.rb', line 46
-
-def to_s
-  if @changes_only
-    @changes.map(&:changes_only).delete_if(&:empty?).join().gsub(/\n+/, "\n").force_encoding('utf-8')
-  else
-    @changes.map(&:to_s).join("\n\n").force_encoding('utf-8')
-  end
-end
-
+
@@ -608,25 +450,7 @@

-

- - - - -
-
-
-
-30
-31
-32
-
-
# File 'lib/doing/changelog/changes.rb', line 30
-
-def versions
-  @changes.select { |change| change.entries&.count > 0 }.map { |change| change.version }
-end
-
+
@@ -634,7 +458,7 @@

diff --git a/docs/doc/Doing/ChronifyArray.html b/docs/doc/Doing/ChronifyArray.html index dea48572..b1fcec26 100644 --- a/docs/doc/Doing/ChronifyArray.html +++ b/docs/doc/Doing/ChronifyArray.html @@ -283,103 +283,7 @@

- - - - - -
-
-
-
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-100
-101
-102
-103
-104
-
-
# File 'lib/doing/chronify/array.rb', line 63
-
-def time_string(format: :dhm)
-  raise InvalidArgument, 'Invalid array, must be [d,h,m]' unless count == 3
-
-  d, h, m = self
-  case format
-  when :clock
-    if d.zero? && h > 24
-      d = (h / 24).floor
-      h = h % 24
-    end
-    format('%<d>02d:%<h>02d:%<m>02d', d: d, h: h, m: m)
-  when :hmclock
-    h += d * 24 if d.positive?
-    format('%<h>02d:%<m>02d', h: h, m: m)
-  when :ydhm
-    to_abbr(years: true, separator: ' ')
-  when :dhm
-    to_abbr(years: false, separator: ' ')
-  when :hm
-    h += d * 24 if d.positive?
-    format('%<h> 4dh %<m>02dm', h: h, m: m)
-  when :m
-    h += d * 24 if d.positive?
-    m += h * 60 if h.positive?
-    format('%<m> 4dm', m: m)
-  when :tight
-    to_abbr(years: true, separator: '')
-  when :natural
-    to_natural.join(', ')
-  when :speech
-    human = to_natural
-    last = human.pop
-    case human.count
-    when 0
-      last
-    when 1
-      "#{human[0]} and #{last}"
-    else
-      human.join(', ') + ", and #{last}"
-    end
-  end
-end
-
+
@@ -391,59 +295,7 @@

-

- - - - -
-
-
-
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-
-
# File 'lib/doing/chronify/array.rb', line 35
-
-def to_abbr(years: false, separator: '')
-  if years
-    y, d, h, m = to_years
-  else
-    y = 0
-    d, h, m = self
-
-    if d.zero? && h > 24
-      d = (h / 24).floor
-      h = h % 24
-    end
-  end
-
-  output = []
-  output.push(format('%<y>dy', y: y)) if y.positive?
-  output.push(format('%<d>dd', d: d)) if d.positive?
-  output.push(format('%<h>dh', h: h)) if h.positive?
-  output.push(format('%<m>dm', m: m)) if m.positive?
-  output.join(separator)
-end
-
+

@@ -455,37 +307,7 @@

-

- - - - -
-
-
-
-25
-26
-27
-28
-29
-30
-31
-32
-33
-
-
# File 'lib/doing/chronify/array.rb', line 25
-
-def to_natural
-  y, d, h, m = to_years
-  human = []
-  human.push(format('%<y>d %<s>s', y: y, s: 'year'.to_p(y))) if y.positive?
-  human.push(format('%<d>d %<s>s', d: d, s: 'day'.to_p(d))) if d.positive?
-  human.push(format('%<h>d %<s>s', h: h, s: 'hour'.to_p(h))) if h.positive?
-  human.push(format('%<m>d %<s>s', m: m, s: 'minute'.to_p(m))) if m.positive?
-  human
-end
-
+
@@ -507,53 +329,7 @@

-
- - - - -
-
-
-
-7
-8
-9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-
-
# File 'lib/doing/chronify/array.rb', line 7
-
-def to_years
-  d, h, m = self
-
-  if d.zero? && h > 24
-    d = (h / 24).floor
-    h = h % 24
-  end
-
-  if d > 365
-    y = (d / 365).floor
-    d = d % 365
-  else
-    y = 0
-  end
-
-  [y, d, h, m]
-end
-
+

@@ -561,7 +337,7 @@

diff --git a/docs/doc/Doing/ChronifyNumeric.html b/docs/doc/Doing/ChronifyNumeric.html index 78155be6..683b5635 100644 --- a/docs/doc/Doing/ChronifyNumeric.html +++ b/docs/doc/Doing/ChronifyNumeric.html @@ -209,51 +209,7 @@

- - - - - -
-
-
-
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-
-
# File 'lib/doing/chronify/numeric.rb', line 14
-
-def format_time(human: false)
-  return [0, 0, 0] if nil?
-
-  seconds = dup.to_i
-  minutes = (seconds / 60).to_i
-  hours = (minutes / 60).to_i
-  if human
-    minutes = (minutes % 60).to_i
-    [0, hours, minutes]
-  else
-    days = (hours / 24).to_i
-    hours = (hours % 24).to_i
-    minutes = (minutes % 60).to_i
-    [days, hours, minutes]
-  end
-end
-
+
@@ -297,25 +253,7 @@

-

- - - - -
-
-
-
-37
-38
-39
-
-
# File 'lib/doing/chronify/numeric.rb', line 37
-
-def time_string(format: :dhm)
-  format_time(human: true).time_string(format: format)
-end
-
+ @@ -323,7 +261,7 @@

diff --git a/docs/doc/Doing/ChronifyString.html b/docs/doc/Doing/ChronifyString.html index 26c8df7d..13eb182a 100644 --- a/docs/doc/Doing/ChronifyString.html +++ b/docs/doc/Doing/ChronifyString.html @@ -393,85 +393,7 @@

- - - - - -
-
-
-
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-
-
# File 'lib/doing/chronify/string.rb', line 27
-
-def chronify(**options)
-  now = Time.now
-  raise Errors::InvalidTimeExpression, "Invalid time expression #{inspect}" if to_s.strip == ''
-
-  secs_ago = if match(/^(\d+)$/)
-               # plain number, assume minutes
-               Regexp.last_match(1).to_i * 60
-             elsif (m = match(/^(?:(?<day>\d+)d)? *(?:(?<hour>\d+)h)? *(?:(?<min>\d+)m)?$/i))
-               # day/hour/minute format e.g. 1d2h30m
-               [[m['day'], 24 * 3600],
-                [m['hour'], 3600],
-                [m['min'], 60]].map { |qty, secs| qty ? (qty.to_i * secs) : 0 }.reduce(0, :+)
-             end
-
-  if secs_ago
-    res = now - secs_ago
-    Doing.logger.debug('Parser:', %(date/time string "#{self}" interpreted as #{res} (#{secs_ago} seconds ago)))
-  else
-    date_string = dup
-    date_string = 'today' if date_string.match(Types::REGEX_DAY) && now.strftime('%a') =~ /^#{Regexp.last_match(1)}/i
-    date_string = "#{options[:context].to_s} #{date_string}" if date_string =~ Types::REGEX_TIME && options[:context]
-
-    res = Chronic.parse(date_string, {
-                          guess: options.fetch(:guess, :begin),
-                          context: options.fetch(:future, false) ? :future : :past,
-                          ambiguous_time_range: 8
-                        })
-
-    Doing.logger.debug('Parser:', %(date/time string "#{self}" interpreted as #{res}))
-  end
-
-  res
-end
-
+
@@ -513,69 +435,7 @@

-

- - - - -
-
-
-
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-
-
# File 'lib/doing/chronify/string.rb', line 70
-
-def chronify_qty
-  minutes = 0
-  case self.strip
-  when /^(\d+):(\d\d)$/
-    minutes += Regexp.last_match(1).to_i * 60
-    minutes += Regexp.last_match(2).to_i
-  when /^(\d+(?:\.\d+)?)([hmd])?/
-    scan(/(\d+(?:\.\d+)?)([hmd])?/).each do |m|
-      amt = m[0]
-      type = m[1].nil? ? 'm' : m[1]
-
-      minutes += case type.downcase
-                 when 'm'
-                   amt.to_i
-                 when 'h'
-                   (amt.to_f * 60).round
-                 when 'd'
-                   (amt.to_f * 60 * 24).round
-                 else
-                   0
-                 end
-    end
-  end
-  minutes * 60
-end
-
+
@@ -622,85 +482,7 @@

-

- - - - -
-
-
-
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-
-
# File 'lib/doing/chronify/string.rb', line 130
-
-def expand_date_tags(additional_tags = nil)
-  iso_rx = /\d{4}-\d\d-\d\d \d\d:\d\d/
-
-  watch_tags = [
-    'start(?:ed)?',
-    'beg[ia]n',
-    'done',
-    'finished',
-    'completed?',
-    'waiting',
-    'defer(?:red)?'
-  ]
-
-  if additional_tags
-    date_tags = additional_tags
-    date_tags = date_tags.split(/ *, */) if date_tags.is_a?(String)
-    date_tags.map! do |tag|
-      tag.sub(/^@/, '').gsub(/\((?!\?:)(.*?)\)/, '(?:\1)').strip
-    end
-    watch_tags.concat(date_tags).uniq!
-  end
-
-  done_rx = /(?<=^| )@(?<tag>#{watch_tags.join('|')})\((?<date>.*?)\)/i
-
-  gsub!(done_rx) do
-    m = Regexp.last_match
-    t = m['tag']
-    d = m['date']
-    future = t =~ /^(done|complete)/ ? false : true
-    parsed_date = d =~ iso_rx ? Time.parse(d) : d.chronify(guess: :begin, future: future)
-    parsed_date.nil? ? m[0] : "@#{t}(#{parsed_date.strftime('%F %R')})"
-  end
-end
-
+
@@ -734,25 +516,7 @@

-

- - - - -
-
-
-
-164
-165
-166
-
-
# File 'lib/doing/chronify/string.rb', line 164
-
-def is_range?
-  self =~ / (to|through|thru|(un)?til|-+) /
-end
-
+
@@ -805,113 +569,7 @@

Process a natural language date -

- - - - -
-
-
-
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-
-
# File 'lib/doing/chronify/string.rb', line 178
-
-def split_date_range
-  time_rx = /^(\d{1,2}(:\d{1,2})?( *(am|pm))?|midnight|noon)$/
-  range_rx = / (to|through|thru|(?:un)?til|-+) /
-
-  date_string = dup
-
-  if date_string.is_range?
-    # Do we want to differentiate between "to" and "through"?
-    # inclusive = date_string =~ / (through|thru|-+) / ? true : false
-    inclusive = true
-
-    dates = date_string.split(range_rx)
-
-    if dates[0].strip =~ time_rx && dates[-1].strip =~ time_rx
-      start = dates[0].strip
-      finish = dates[-1].strip
-    else
-      start = dates[0].chronify(guess: :begin, future: false)
-      finish = dates[-1].chronify(guess: inclusive ? :end : :begin, future: true)
-    end
-
-    raise Errors::InvalidTimeExpression, "Unrecognized date string (#{dates[0]})" if start.nil?
-
-    raise Errors::InvalidTimeExpression, "Unrecognized date string (#{dates[-1]})" if finish.nil?
-
-  else
-    if date_string.strip =~ time_rx
-      start = date_string.strip
-      finish = '11:59pm'
-    else
-      start = date_string.strip.chronify(guess: :begin, future: false)
-      finish = start + (24 * 60 * 60)
-    end
-    raise Errors::InvalidTimeExpression, 'Unrecognized date string' unless start
-
-  end
-
-
-  if start.is_a? String
-    Doing.logger.debug('Parser:',
-                       "--from string interpreted as time span, from #{start || '12am'} to #{finish || '11:59pm'}")
-  else
-    Doing.logger.debug('Parser:',
-                       "date range interpreted as #{start.strftime('%F %R')} -- #{finish ? finish.strftime('%F %R') : 'now'}")
-  end
-  [start, finish]
-end
-
+
@@ -954,25 +612,7 @@

-

- - - - -
-
-
-
-117
-118
-119
-
-
# File 'lib/doing/chronify/string.rb', line 117
-
-def time_string(format: :dhm)
-  to_seconds.time_string(format: format)
-end
-
+
@@ -1024,39 +664,7 @@

-

- - - - -
-
-
-
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-
-
# File 'lib/doing/chronify/string.rb', line 101
-
-def to_seconds
-  mtch = match(/(\d+):(\d+):(\d+)/)
-
-  raise Errors::DoingRuntimeError, "Invalid time string: #{self}" unless mtch
-
-  h = mtch[1]
-  m = mtch[2]
-  s = mtch[3]
-  (h.to_i * 60 * 60) + (m.to_i * 60) + s.to_i
-end
-
+ @@ -1064,7 +672,7 @@

diff --git a/docs/doc/Doing/Color.html b/docs/doc/Doing/Color.html index ed067a73..175fbd21 100644 --- a/docs/doc/Doing/Color.html +++ b/docs/doc/Doing/Color.html @@ -455,25 +455,7 @@

Turn color on or off based on T

- - - - - -
-
-
-
-201
-202
-203
-
-
# File 'lib/doing/colors.rb', line 201
-
-def coloring
-  @coloring ||= true
-end
-
+ @@ -516,25 +498,7 @@

- - - - - -
-
-
-
-190
-191
-192
-
-
# File 'lib/doing/colors.rb', line 190
-
-def coloring?
-  @coloring
-end
-
+
@@ -612,49 +576,7 @@

Convert a templated string

-
- - - - -
-
-
-
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-
-
# File 'lib/doing/colors.rb', line 224
-
-def template(input)
-  input = input.join(' ') if input.is_a? Array
-  fmt = input.gsub(/%/, '%%')
-  fmt = fmt.gsub(/(?<!\\u|\$)\{(\w+)\}/i) do
-    Regexp.last_match(1).split('').map { |c| "%<#{c}>s" }.join('')
-  end
-
-  colors = { w: white, k: black, g: green, l: blue,
-             y: yellow, c: cyan, m: magenta, r: red,
-             W: bgwhite, K: bgblack, G: bggreen, L: bgblue,
-             Y: bgyellow, C: bgcyan, M: bgmagenta, R: bgred,
-             d: dark, b: bold, u: underline, i: italic, x: reset }
-
-  fmt.empty? ? input : format(fmt, colors)
-end
-
+
@@ -682,25 +604,7 @@

-
- - - - -
-
-
-
-314
-315
-316
-
-
# File 'lib/doing/colors.rb', line 314
-
-def attributes
-  ATTRIBUTE_NAMES
-end
-
+
@@ -712,43 +616,7 @@

-

- - - - -
-
-
-
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-
-
# File 'lib/doing/colors.rb', line 286
-
-def rgb(hex)
-  is_bg = hex.match(/^bg?#/) ? true : false
-  hex_string = hex.sub(/^([fb]g?)?#/, '')
-
-  parts = hex_string.match(/(?<r>..)(?<g>..)(?<b>..)/)
-  t = []
-  %w[r g b].each do |e|
-    t << parts[e].hex
-  end
-  color =
-  "\e[#{is_bg ? '48' : '38'};2;#{t.join(';')}m"
-end
-
+

@@ -788,31 +656,7 @@

-

- - - - -
-
-
-
-90
-91
-92
-93
-94
-95
-
-
# File 'lib/doing/colors.rb', line 90
-
-def support?(feature)
-  case feature
-  when :clear
-    !String.instance_methods(false).map(&:to_sym).include?(:clear)
-  end
-end
-
+
@@ -835,41 +679,7 @@

-
- - - - -
-
-
-
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-
-
# File 'lib/doing/colors.rb', line 301
-
-def uncolor(string = nil) # :yields:
-  if block_given?
-    yield.to_str.gsub(ESCAPE_REGEX, '')
-  elsif string.respond_to?(:to_str)
-    string.to_str.gsub(ESCAPE_REGEX, '')
-  elsif respond_to?(:to_str)
-    to_str.gsub(ESCAPE_REGEX, '')
-  else
-    ''
-  end
-end
-
+

@@ -877,7 +687,7 @@

diff --git a/docs/doc/Doing/Completion.html b/docs/doc/Doing/Completion.html index ab4c4314..37bd2dc8 100644 --- a/docs/doc/Doing/Completion.html +++ b/docs/doc/Doing/Completion.html @@ -414,51 +414,7 @@

- - - - - -
-
-
-
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-
-
# File 'lib/doing/completion.rb', line 68
-
-def generate_completion(type: 'zsh', file: :default, link: true)
-  return generate_all if type =~ /^all$/i
-
-  file = file == :default ? default_file(type) : file
-  file = validate_target(file)
-  result = generate_type(type)
-
-  if file =~ /^stdout$/i
-    $stdout.puts result
-  else
-    File.open(file, 'w') { |f| f.puts result }
-    Doing.logger.warn('File written:', "#{type} completions written to #{file}")
-
-    link_completion_type(type, file) if link
-  end
-end
-
+
@@ -470,41 +426,7 @@

-

- - - - -
-
-
-
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-
-
# File 'lib/doing/completion.rb', line 19
-
-def get_help_sections(command = "")
-  res = `doing help #{command}|command cat`.strip
-  scanned = res.scan(SECTIONS_RX)
-  sections = {}
-  scanned.each do |sect|
-    title = sect[0].downcase.strip.gsub(/ +/, '_').to_sym
-    content = sect[1].split(/\n/).map(&:strip).delete_if(&:empty?)
-    sections[title] = content
-  end
-  sections
-end
-
+

@@ -516,43 +438,7 @@

-

- - - - -
-
-
-
-96
-97
-98
-99
-100
-101
-102
-103
-104
-105
-106
-107
-
-
# File 'lib/doing/completion.rb', line 96
-
-def install_builtin(type)
-  FileUtils.mkdir_p(default_dir)
-  src = File.expand_path(File.join(File.dirname(__FILE__), '..', 'completion', default_filenames[type]))
-
-  if File.exist?(File.join(default_dir, default_filenames[type]))
-    return unless Doing::Prompt.yn("Update #{type} completion script", default_response: 'n')
-
-  end
-
-  FileUtils.cp(src, default_dir)
-  Doing.logger.warn('File written:', "#{type} completions saved to #{default_file(type)}")
-end
-
+
@@ -586,39 +472,7 @@
- - - - -
-
-
-
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-
-
# File 'lib/doing/completion.rb', line 85
-
-def link_default(type)
-  type = normalize_type(type)
-  raise InvalidArgument, 'Unrecognized shell specified' if type == :invalid
-
-  return %i[zsh bash fish fig].each { |t| link_default(t) } if type == :all
-
-  install_builtin(type)
-
-  link_completion_type(type, File.join(default_dir, default_filenames[type]))
-end
-
+
@@ -630,51 +484,7 @@

-

- - - - -
-
-
-
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-
-
# File 'lib/doing/completion.rb', line 109
-
-def normalize_type(type)
-  case type.to_s
-  when /^fig/i
-    :fig
-  when /^f/i
-    :fish
-  when /^b/i
-    :bash
-  when /^z/i
-    :zsh
-  when /^a/i
-    :all
-  else
-    :invalid
-  end
-end
-
+
@@ -686,39 +496,7 @@

-

- - - - -
-
-
-
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-
-
# File 'lib/doing/completion.rb', line 47
-
-def parse_command(command)
-  res = command.match(COMMAND_RX)
-  commands = [res['cmd']]
-  commands.concat(res['alias'].split(/, /).delete_if(&:empty?)) if res['alias']
-
-  {
-    commands: commands,
-    description: res['desc'].short_desc
-  }
-end
-
+
@@ -730,25 +508,7 @@

-

- - - - -
-
-
-
-58
-59
-60
-
-
# File 'lib/doing/completion.rb', line 58
-
-def parse_commands(commands)
-  commands.map { |cmd| parse_command(cmd) }
-end
-
+
@@ -760,41 +520,7 @@

-

- - - - -
-
-
-
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-
-
# File 'lib/doing/completion.rb', line 31
-
-def parse_option(option)
-  res = option.match(OPTIONS_RX)
-  return nil unless res
-
-  {
-    short: res['short'],
-    long: res['long'],
-    arg: res['arg'],
-    description: res['desc'].short_desc
-  }
-end
-
+
@@ -806,25 +532,7 @@

-

- - - - -
-
-
-
-43
-44
-45
-
-
# File 'lib/doing/completion.rb', line 43
-
-def parse_options(options)
-  options.map { |opt| parse_option(opt) }
-end
-
+
@@ -832,7 +540,7 @@

diff --git a/docs/doc/Doing/Completion/BashCompletions.html b/docs/doc/Doing/Completion/BashCompletions.html index e9055197..40b9053f 100644 --- a/docs/doc/Doing/Completion/BashCompletions.html +++ b/docs/doc/Doing/Completion/BashCompletions.html @@ -319,35 +319,7 @@

-
- - - - -
-
-
-
-125
-126
-127
-128
-129
-130
-131
-132
-
-
# File 'lib/doing/completion/bash_completion.rb', line 125
-
-def initialize
-  data = Completion.get_help_sections
-  @global_options = Completion.parse_options(data[:global_options])
-  @commands = Completion.parse_commands(data[:commands])
-  @bar = TTY::ProgressBar.new("\033[0;0;33mGenerating Bash completions: \033[0;35;40m[:bar] :status\033[0m", total: @commands.count + 1, bar_format: :square, hide_cursor: true, status: 'Reading subcommands')
-  width = TTY::Screen.columns - 45
-  @bar.resize(width)
-end
-
+ @@ -376,25 +348,7 @@

-
- - - - -
-
-
-
-7
-8
-9
-
-
# File 'lib/doing/completion/bash_completion.rb', line 7
-
-def commands
-  @commands
-end
-
+ @@ -418,25 +372,7 @@

-
- - - - -
-
-
-
-7
-8
-9
-
-
# File 'lib/doing/completion/bash_completion.rb', line 7
-
-def global_options
-  @global_options
-end
-
+ @@ -455,81 +391,7 @@

-

- - - - -
-
-
-
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-
-
# File 'lib/doing/completion/bash_completion.rb', line 63
-
-def command_function(command, options, type)
-  long_options = []
-  short_options = []
-
-  options.each do |o|
-    next if o.nil?
-
-    long_options << o[:long] if o[:long]
-    short_options << o[:short] if o[:short]
-  end
-
-  long = long_options.map! {|o| "--#{o}"}.join(' ')
-  short = short_options.map! {|o| "-#{o}"}.join(' ')
-  words = ''
-  logic = ''
-  words, logic = get_words(type) if type && type.is_a?(String)
-
-  func = <<~ENDFUNC
-  _doing_#{command}() {
-    #{words}
-    if [[ "$token" == --* ]]; then
-      COMPREPLY=( $( compgen -W '#{long}' -- $token ) )
-    elif [[ "$token" == -* ]]; then
-      COMPREPLY=( $( compgen -W '#{short} #{long}' -- $token ) )
-    #{logic}
-    fi
-  }
-  ENDFUNC
-
-  func
-end
-
+
@@ -541,37 +403,7 @@

-

- - - - -
-
-
-
-134
-135
-136
-137
-138
-139
-140
-141
-142
-
-
# File 'lib/doing/completion/bash_completion.rb', line 134
-
-def generate_completions
-  @bar.start
-  out = []
-  out << main_function
-  out << 'complete -F _doing doing'
-  @bar.advance(status: '')
-  @bar.finish
-  out.join("\n")
-end
-
+
@@ -583,77 +415,7 @@

-

- - - - -
-
-
-
-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
-
-
# File 'lib/doing/completion/bash_completion.rb', line 95
-
-def get_words(type)
-  func = <<~EOFUNC
-    OLD_IFS="$IFS"
-    local token=${COMP_WORDS[$COMP_CWORD]}
-    IFS=$'\t'
-    local words=$(doing #{type})
-    IFS="$OLD_IFS"
-  EOFUNC
-
-  logic = <<~EOLOGIC
-    else
-      local nocasematchWasOff=0
-      shopt nocasematch >/dev/null || nocasematchWasOff=1
-      (( nocasematchWasOff )) && shopt -s nocasematch
-      local w matches=()
-      OLD_IFS="$IFS"
-      IFS=$'\t'‰
-      for w in $words; do
-        if [[ "$w" == "$token"* ]]; then
-          matches+=("${w// /\ }")
-        fi
-      done
-      IFS="$OLD_IFS"
-      (( nocasematchWasOff )) && shopt -u nocasematch
-      COMPREPLY=("${matches[@]}")
-  EOLOGIC
-
-  [func, logic]
-end
-
+
@@ -665,125 +427,7 @@

-

- - - - -
-
-
-
-9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-
-
# File 'lib/doing/completion/bash_completion.rb', line 9
-
-def main_function
-  first = true
-  out = []
-  logic = []
-
-  @commands.each_with_index do |cmd, i|
-    @bar.advance(status: cmd[:commands].first)
-
-    data = Completion.get_help_sections(cmd[:commands].first)
-
-    arg = data[:synopsis].join(' ').strip.split(/ /).last
-    case arg
-    when /(path|file)/i
-      type = :file
-    when /sect/i
-      type = 'sections'
-    when /view/i
-      type = 'views'
-    else
-      type = nil
-    end
-
-    if data[:command_options]
-      options = Completion.parse_options(data[:command_options])
-      out << command_function(cmd[:commands].first, options, type)
-
-      if first
-        op = 'if'
-        first = false
-      else
-        op = 'elif'
-      end
-      logic << %(#{op} [[ $last =~ (#{cmd[:commands].join('|')}) ]]; then _doing_#{cmd[:commands].first})
-    end
-  end
-
-  out << <<~EOFUNC
-    _doing()
-    {
-      local last="${@: -1}"
-      local token=${COMP_WORDS[$COMP_CWORD]}
-
-      #{logic.join("\n    ")}
-      else
-        OLD_IFS="$IFS"
-        IFS=$'\n'
-        COMPREPLY=( $(compgen -W "$(doing help -c)" -- $token) )
-        IFS="$OLD_IFS"
-      fi
-    }
-  EOFUNC
-  out.join("\n")
-end
-
+
@@ -791,7 +435,7 @@

diff --git a/docs/doc/Doing/Completion/FigCompletions.html b/docs/doc/Doing/Completion/FigCompletions.html index c03f2b52..36bf171f 100644 --- a/docs/doc/Doing/Completion/FigCompletions.html +++ b/docs/doc/Doing/Completion/FigCompletions.html @@ -319,35 +319,7 @@

-
- - - - -
-
-
-
-106
-107
-108
-109
-110
-111
-112
-113
-
-
# File 'lib/doing/completion/fig_completion.rb', line 106
-
-def initialize
-  data = Completion.get_help_sections
-  @global_options = Completion.parse_options(data[:global_options])
-  @commands = Completion.parse_commands(data[:commands])
-  @bar = TTY::ProgressBar.new(" \033[0;0;33mGenerating Fig completions: \033[0;35;40m[:bar] :status\033[0m", total: @commands.count + 1, bar_format: :square, hide_cursor: true, status: 'processing subcommands')
-  width = TTY::Screen.columns - 45
-  @bar.resize(width)
-end
-
+ @@ -376,25 +348,7 @@

-
- - - - -
-
-
-
-13
-14
-15
-
-
# File 'lib/doing/completion/fig_completion.rb', line 13
-
-def commands
-  @commands
-end
-
+ @@ -418,25 +372,7 @@

-
- - - - -
-
-
-
-13
-14
-15
-
-
# File 'lib/doing/completion/fig_completion.rb', line 13
-
-def global_options
-  @global_options
-end
-
+ @@ -455,27 +391,7 @@

-

- - - - -
-
-
-
-115
-116
-117
-118
-
-
# File 'lib/doing/completion/fig_completion.rb', line 115
-
-def generate_completions
-  @bar.start
-  generate_helpers
-end
-
+
@@ -487,49 +403,7 @@

-

- - - - -
-
-
-
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-
-
# File 'lib/doing/completion/fig_completion.rb', line 15
-
-def generate_helpers
-  out=<<~EOFUNCTIONS
-  const completionSpec: Fig.Spec = {
-    name: "doing",
-    description: "A CLI for a What Was I Doing system",
-    subcommands: [
-      #{generate_subcommand_completions.join("\n    ")}
-    ],
-  };
-  export default completionSpec;
-  EOFUNCTIONS
-  @bar.advance(status: '')
-  @bar.finish
-  out
-end
-
+
@@ -541,53 +415,7 @@

-

- - - - -
-
-
-
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-
-
# File 'lib/doing/completion/fig_completion.rb', line 31
-
-def generate_subcommand_completions
-  out = []
-  indent = '      '
-  @commands.each do |cmd|
-    cmd[:commands].each do |c|
-      out << <<~EOCOMMAND
-        {
-        #{indent}name: "#{c}",
-        #{indent}description: "#{cmd[:description].sanitize}",
-        #{indent}#{generate_subcommand_option_completions(cmd)}
-            },
-      EOCOMMAND
-    end
-  end
-
-  out
-end
-
+
@@ -599,131 +427,7 @@

- - -
-
-
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-100
-101
-102
-103
-104
- - -
# File 'lib/doing/completion/fig_completion.rb', line 49
-
-def generate_subcommand_option_completions(cmd, indent: '          ')
-  out = []
-
-  @bar.advance(status: cmd[:commands].first)
-
-  data = Completion.get_help_sections(cmd[:commands].first)
-
-  option_arr = []
-
-  if data[:command_options]
-    Completion.parse_options(data[:command_options]).each do |option|
-      next if option.nil?
-
-      arg = ''
-
-      if option[:arg]
-        arg =<<~EOARG
-        args: {
-        #{indent}        name: "#{option[:arg]}",
-        #{indent}        description: "#{option[:arg]}",
-        #{indent}  },
-        EOARG
-      end
-
-      if option[:short]
-        opt_data =<<~EOOPT
-        {
-        #{indent}  name: ["-#{option[:short]}", "--#{option[:long]}"],
-        #{indent}  description: "#{option[:description].sanitize}",
-        #{indent}  #{arg}
-        #{indent}},
-        EOOPT
-      else
-        opt_data = <<~EOOPT
-        {
-        #{indent}  name: ["--#{option[:long]}"],
-        #{indent}  description: "#{option[:description].sanitize}",
-        #{indent}  #{arg}
-        #{indent}},
-        EOOPT
-      end
-
-      option_arr << opt_data
-
-    end
-
-    cmd_opts = <<~EOCMD
-      options: [
-      #{indent}#{option_arr.join("\n#{indent}")}
-              ],
-    EOCMD
-    out << cmd_opts
-  end
-
-  out.join("\n")
-end
- - - +

@@ -731,7 +435,7 @@

- Generated on Sun Dec 1 11:01:06 2024 by + Generated on Sat Dec 14 15:35:49 2024 by yard 0.9.37 (ruby-3.3.0). diff --git a/docs/doc/Doing/Completion/FishCompletions.html b/docs/doc/Doing/Completion/FishCompletions.html index 9cbec089..183e1d2d 100644 --- a/docs/doc/Doing/Completion/FishCompletions.html +++ b/docs/doc/Doing/Completion/FishCompletions.html @@ -319,35 +319,7 @@

-
- - - - -
-
-
-
-231
-232
-233
-234
-235
-236
-237
-238
-
-
# File 'lib/doing/completion/fish_completion.rb', line 231
-
-def initialize
-  data = Completion.get_help_sections
-  @global_options = Completion.parse_options(data[:global_options])
-  @commands = Completion.parse_commands(data[:commands])
-  @bar = TTY::ProgressBar.new("\033[0;0;33mGenerating Fish completions: \033[0;35;40m[:bar] :status\033[0m", total: @commands.count + 1, bar_format: :square, hide_cursor: true, status: 'processing subcommands')
-  width = TTY::Screen.columns - 45
-  @bar.resize(width)
-end
-
+ @@ -376,25 +348,7 @@

-
- - - - -
-
-
-
-8
-9
-10
-
-
# File 'lib/doing/completion/fish_completion.rb', line 8
-
-def commands
-  @commands
-end
-
+ @@ -418,25 +372,7 @@

-
- - - - -
-
-
-
-8
-9
-10
-
-
# File 'lib/doing/completion/fish_completion.rb', line 8
-
-def global_options
-  @global_options
-end
-
+ @@ -455,39 +391,7 @@

-

- - - - -
-
-
-
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-
-
# File 'lib/doing/completion/fish_completion.rb', line 240
-
-def generate_completions
-  @bar.start
-  out = []
-  out << generate_helpers
-  out << generate_subcommand_completions
-  out << generate_subcommand_option_completions
-  @bar.advance(status: '')
-  @bar.finish
-  out.join("\n")
-end
-
+
@@ -499,283 +403,7 @@

-

- - - - -
-
-
-
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-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
-
-
# File 'lib/doing/completion/fish_completion.rb', line 10
-
-def generate_helpers
-  <<~EOFUNCTIONS
-    function __fish_doing_needs_command
-      # Figure out if the current invocation already has a command.
-
-      set -l opts color h-help config_file= f-doing_file= n-notes v-version stdout debug default x-noauto no p-pager q-quiet yes
-      set cmd (commandline -opc)
-      set -e cmd[1]
-      argparse -s $opts -- $cmd 2>/dev/null
-      or return 0
-      # These flags function as commands, effectively.
-      if set -q argv[1]
-        # Also print the command, so this can be used to figure out what it is.
-        echo $argv[1]
-        return 1
-      end
-      return 0
-    end
-
-    function __fish_doing_using_command
-      set -l cmd (__fish_doing_needs_command)
-      test -z "$cmd"
-      and return 1
-      contains -- $cmd $argv
-      and return 0
-    end
-
-    function __fish_doing_cache_timer_expired
-      set -l timer __fish_doing_cache_timer_$argv[1]
-      if not set -q $timer
-        set -g $timer (date '+%s')
-      end
-
-      if test (math (date '+%s') - $$timer) -gt $argv[2]
-        set -g $timer (date '+%s')
-        return 1
-      end
-
-      return 0
-    end
-
-    function __fish_doing_subcommands
-      if not set -q __fish_doing_subcommands_cache
-        or __fish_doing_cache_timer_expired subcommands 86400
-        set -g -a __fish_doing_subcommands_cache (doing help -c)
-      end
-      printf '%s\n' $__fish_doing_subcommands_cache
-    end
-
-    function __fish_doing_complete_sections
-      if not set -q __fish_doing_sections_cache
-        or __fish_doing_cache_timer_expired sections 3600
-        set -g -a __fish_doing_sections_cache (doing sections -c)
-      end
-      printf '%s\n' $__fish_doing_sections_cache
-      __fish_doing_complete_show_tag
-    end
-
-    function __fish_doing_complete_views
-      if not set -q __fish_doing_views_cache
-        or __fish_doing_cache_timer_expired views 3600
-        set -g -a __fish_doing_views_cache (doing views -c)
-      end
-      printf '%s\n' $__fish_doing_views_cache
-    end
-
-    function __fish_doing_export_plugin
-      if not set -q __fish_doing_export_plugin_cache
-        or __fish_doing_cache_timer_expired export_plugins 3600
-        set -g -a __fish_doing_export_plugin_cache (doing plugins --type export -c)
-      end
-      printf '%s\n' $__fish_doing_export_plugin_cache
-    end
-
-    function __fish_doing_import_plugin
-      if not set -q __fish_doing_import_plugin_cache
-        or __fish_doing_cache_timer_expired import_plugins 3600
-        set -g -a __fish_doing_import_plugin_cache (doing plugins --type import -c)
-      end
-      printf '%s\n' $__fish_doing_import_plugin_cache
-    end
-
-    function __fish_doing_complete_template
-      if not set -q __fish_doing_template_cache
-        or __fish_doing_cache_timer_expired template 3600
-        set -g -a __fish_doing_template_cache (doing template -c)
-      end
-      printf '%s\n' $__fish_doing_template_cache
-    end
-
-    function __fish_doing_complete_tag
-      if not set -q __fish_doing_tag_cache
-        or __fish_doing_cache_timer_expired tags 60
-        set -g -a __fish_doing_tag_cache (doing tags)
-      end
-      printf '%s\n' $__fish_doing_tag_cache
-    end
-
-    function __fish_doing_complete_show_tag
-      if not set -q __fish_doing_tag_cache
-        or __fish_doing_cache_timer_expired tags 60
-        set -g -a __fish_doing_tag_cache (doing tags)
-      end
-      printf '@%s\n' $__fish_doing_tag_cache
-    end
-
-    function __fish_doing_complete_args
-      for cmd in (doing commands_accepting -c $argv[1])
-        complete -x -c doing -l $argv[1] -n "__fish_doing_using_command $cmd" -a "(__fish_doing_complete_$argv[1])"
-      end
-    end
-
-    complete -c doing -f
-    complete -xc doing -n '__fish_doing_needs_command' -a '(__fish_doing_subcommands)'
-
-    complete -f -c doing -n '__fish_doing_using_command show' -a '(__fish_doing_complete_sections)'
-    complete -f -c doing -n '__fish_doing_using_command view' -a '(__fish_doing_complete_views)'
-    complete -f -c doing -n '__fish_doing_using_command template' -a '(__fish_doing_complete_templates)'
-    complete -f -c doing -s t -l type -x -n '__fish_doing_using_command import' -a '(__fish_doing_import_plugins)'
-    complete -f -c doing -n '__fish_doing_using_command help' -a '(__fish_doing_subcommands)'
-
-    # complete -xc doing -n '__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from (doing help -c)' -a "(doing help -c)"
-
-    function __fish_doing_complete_args
-      for cmd in (doing commands_accepting -c $argv[1])
-        complete -x -c doing -l $argv[1] -n "__fish_doing_using_command $cmd" -a "(__fish_doing_complete_$argv[1])"
-      end
-    end
-
-    __fish_doing_complete_args tag
-  EOFUNCTIONS
-end
-
+
@@ -787,39 +415,7 @@

-

- - - - -
-
-
-
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-
-
# File 'lib/doing/completion/fish_completion.rb', line 143
-
-def generate_subcommand_completions
-  out = []
-  @commands.each do |cmd|
-    desc = Shellwords.escape(cmd[:description])
-    cmds = cmd[:commands].join(' ')
-    out << "complete -xc doing -n '__fish_doing_needs_command' -a '#{cmds}' -d #{desc}"
-  end
-
-  out.join("\n")
-end
-
+
@@ -831,171 +427,7 @@

- - -
-
-
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
- - -
# File 'lib/doing/completion/fish_completion.rb', line 154
-
-def generate_subcommand_option_completions
-
-  out = []
-  need_export = []
-  need_bool = []
-  need_case = []
-  need_sort = []
-  need_tag_sort = []
-  need_tag_order = []
-  need_age = []
-  need_section = []
-
-  @commands.each_with_index do |cmd, i|
-    @bar.advance(status: cmd[:commands].first)
-    data = Completion.get_help_sections(cmd[:commands].first)
-
-    if data[:synopsis].join(' ').strip.split(/ /).last =~ /(path|file)/i
-      out << "complete -c doing -F -n '__fish_doing_using_command #{cmd[:commands].join(" ")}'"
-    end
-
-    if data[:command_options]
-      Completion.parse_options(data[:command_options]).each do |option|
-        next if option.nil?
-
-        arg = option[:arg] ? '-r' : ''
-        short = option[:short] ? "-s #{option[:short]}" : ''
-        long = option[:long] ? "-l #{option[:long]}" : ''
-        out << "complete -c doing #{long} #{short} -f #{arg} -n '__fish_doing_using_command #{cmd[:commands].join(' ')}' -d #{Shellwords.escape(option[:description])}"
-
-        need_export.concat(cmd[:commands]) if option[:long] == 'output'
-        need_bool.concat(cmd[:commands]) if option[:long] == 'bool'
-        need_case.concat(cmd[:commands]) if option[:long] == 'case'
-        need_sort.concat(cmd[:commands]) if option[:long] == 'sort'
-        need_tag_sort.concat(cmd[:commands]) if option[:long] == 'tag_sort'
-        need_tag_order.concat(cmd[:commands]) if option[:long] == 'tag_order'
-        need_age.concat(cmd[:commands]) if option[:long] == 'age'
-        need_section.concat(cmd[:commands]) if option[:long] == 'section'
-      end
-    end
-  end
-
-  unless need_export.empty?
-    out << "complete -f -c doing -s o -l output -x -n '__fish_doing_using_command #{need_export.join(' ')}' -a '(__fish_doing_export_plugin)'"
-  end
-
-  unless need_bool.empty?
-    out << "complete -f -c doing -s b -l bool -x -n '__fish_doing_using_command #{need_bool.join(' ')}' -a 'and or not pattern'"
-  end
-
-  unless need_case.empty?
-    out << "complete -f -c doing -l case -x -n '__fish_doing_using_command #{need_case.join(' ')}' -a 'case-sensitive ignore smart'"
-  end
-
-  unless need_sort.empty?
-    out << "complete -f -c doing -l sort -x -n '__fish_doing_using_command #{need_sort.join(' ')}' -a 'asc desc'"
-  end
-
-  unless need_tag_sort.empty?
-    out << "complete -f -c doing -l tag_sort -x -n '__fish_doing_using_command #{need_tag_sort.join(' ')}' -a 'name time'"
-  end
-
-  unless need_tag_order.empty?
-    out << "complete -f -c doing -l tag_order -x -n '__fish_doing_using_command #{need_tag_order.join(' ')}' -a 'asc desc'"
-  end
-
-  unless need_age.empty?
-    out << "complete -f -c doing -s a -l age -x -n '__fish_doing_using_command #{need_age.join(' ')}' -a 'oldest newest'"
-  end
-
-  unless need_section.empty?
-    out << "complete -f -c doing -s s -l section -x -n '__fish_doing_using_command #{need_section.join(' ')}' -a '(__fish_doing_complete_sections)'"
-  end
-
-  # clear
-  out.join("\n")
-end
- - - +

@@ -1003,7 +435,7 @@

- Generated on Sun Dec 1 11:01:06 2024 by + Generated on Sat Dec 14 15:35:49 2024 by yard 0.9.37 (ruby-3.3.0). diff --git a/docs/doc/Doing/Completion/StringUtils.html b/docs/doc/Doing/Completion/StringUtils.html index d713126c..d1ac665b 100644 --- a/docs/doc/Doing/Completion/StringUtils.html +++ b/docs/doc/Doing/Completion/StringUtils.html @@ -218,33 +218,7 @@

- - - - - -
-
-
-
-19
-20
-21
-22
-23
-24
-25
-
-
# File 'lib/doing/completion/completion_string.rb', line 19
-
-def ltrunc(max)
-  if length > max
-    sub(/^.*?(.{#{max - 3}})$/, '...\1')
-  else
-    self
-  end
-end
-
+
@@ -256,25 +230,7 @@

-

- - - - -
-
-
-
-27
-28
-29
-
-
# File 'lib/doing/completion/completion_string.rb', line 27
-
-def ltrunc!(max)
-  replace ltrunc(max)
-end
-
+

@@ -313,25 +269,7 @@

-

- - - - -
-
-
-
-10
-11
-12
-
-
# File 'lib/doing/completion/completion_string.rb', line 10
-
-def short_desc
-  split(/[,.]/)[0].sub(/ \(.*?\)?$/, '').strip
-end
-
+ @@ -339,7 +277,7 @@

diff --git a/docs/doc/Doing/Completion/ZshCompletions.html b/docs/doc/Doing/Completion/ZshCompletions.html index 6ecf0f45..058634c3 100644 --- a/docs/doc/Doing/Completion/ZshCompletions.html +++ b/docs/doc/Doing/Completion/ZshCompletions.html @@ -319,35 +319,7 @@

-
- - - - -
-
-
-
-92
-93
-94
-95
-96
-97
-98
-99
-
-
# File 'lib/doing/completion/zsh_completion.rb', line 92
-
-def initialize
-  data = Completion.get_help_sections
-  @global_options = Completion.parse_options(data[:global_options])
-  @commands = Completion.parse_commands(data[:commands])
-  @bar = TTY::ProgressBar.new(" \033[0;0;33mGenerating Zsh completions: \033[0;35;40m[:bar] :status\033[0m", total: @commands.count + 1, bar_format: :square, hide_cursor: true, status: 'processing subcommands')
-  width = TTY::Screen.columns - 45
-  @bar.resize(width)
-end
-
+ @@ -376,25 +348,7 @@

-
- - - - -
-
-
-
-13
-14
-15
-
-
# File 'lib/doing/completion/zsh_completion.rb', line 13
-
-def commands
-  @commands
-end
-
+ @@ -418,25 +372,7 @@

-
- - - - -
-
-
-
-13
-14
-15
-
-
# File 'lib/doing/completion/zsh_completion.rb', line 13
-
-def global_options
-  @global_options
-end
-
+ @@ -455,27 +391,7 @@

-

- - - - -
-
-
-
-101
-102
-103
-104
-
-
# File 'lib/doing/completion/zsh_completion.rb', line 101
-
-def generate_completions
-  @bar.start
-  generate_helpers
-end
-
+
@@ -487,87 +403,7 @@

-

- - - - -
-
-
-
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-
-
# File 'lib/doing/completion/zsh_completion.rb', line 15
-
-def generate_helpers
-  out=<<~EOFUNCTIONS
-    compdef _doing doing
-
-    function _doing() {
-        local line state
-
-        function _commands {
-            local -a commands
-
-            commands=(
-                      #{generate_subcommand_completions.join("\n                  ")}
-            )
-            _describe 'command' commands
-        }
-
-        _arguments -C \
-                "1: :_commands" \
-                "*::arg:->args"
-
-
-
-        case $line[1] in
-            #{generate_subcommand_option_completions(indent: '            ').join("\n            ")}
-        esac
-
-        _arguments -s $args
-    }
-
-  EOFUNCTIONS
-  @bar.advance(status: '')
-  @bar.finish
-  out
-end
-
+
@@ -579,37 +415,7 @@

-

- - - - -
-
-
-
-50
-51
-52
-53
-54
-55
-56
-57
-58
-
-
# File 'lib/doing/completion/zsh_completion.rb', line 50
-
-def generate_subcommand_completions
-  out = []
-  @commands.each_with_index do |cmd, i|
-    cmd[:commands].each do |c|
-      out << "'#{c}:#{cmd[:description].gsub(/'/, '\\\'')}'"
-    end
-  end
-  out
-end
-
+
@@ -621,81 +427,7 @@

- - -
-
-
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
- - -
# File 'lib/doing/completion/zsh_completion.rb', line 60
-
-def generate_subcommand_option_completions(indent: '        ')
-
-  out = []
-
-  @commands.each_with_index do |cmd, i|
-    @bar.advance(status: cmd[:commands].first)
-
-    data = Completion.get_help_sections(cmd[:commands].first)
-    option_arr = []
-
-    if data[:command_options]
-      Completion.parse_options(data[:command_options]).each do |option|
-        next if option.nil?
-
-        arg = option[:arg] ? ":#{option[:arg]}:" : ''
-
-        option_arr << if option[:short]
-                        %({'(--#{option[:long]})-#{option[:short]}','(-#{option[:short]})--#{option[:long]}'}"[#{option[:description].sanitize}]#{arg}")
-                      else
-                        %("--#{option[:long]}[#{option[:description].sanitize}]#{arg}")
-                      end
-      end
-    end
-
-    cmd[:commands].each do |c|
-      out << "#{c}) \n#{indent}    args=( #{option_arr.join(' ')} )\n#{indent};;"
-    end
-  end
-
-  out
-end
- - - +

@@ -703,7 +435,7 @@

- Generated on Sun Dec 1 11:01:06 2024 by + Generated on Sat Dec 14 15:35:49 2024 by yard 0.9.37 (ruby-3.3.0). diff --git a/docs/doc/Doing/Configuration.html b/docs/doc/Doing/Configuration.html index 2e3296a8..8a426f60 100644 --- a/docs/doc/Doing/Configuration.html +++ b/docs/doc/Doing/Configuration.html @@ -679,29 +679,7 @@

-
- - - - -
-
-
-
-121
-122
-123
-124
-125
-
-
# File 'lib/doing/configuration.rb', line 121
-
-def initialize(file = nil, options: {})
-  @config_file = file.nil? ? default_config_file : File.expand_path(file)
-
-  @settings = configure(options)
-end
-
+ @@ -720,25 +698,7 @@

-

- - - - -
-
-
-
-127
-128
-129
-
-
# File 'lib/doing/configuration.rb', line 127
-
-def config_file
-  @config_file ||= default_config_file
-end
-
+ @@ -752,25 +712,7 @@

-

- - - - -
-
-
-
-12
-13
-14
-
-
# File 'lib/doing/configuration.rb', line 12
-
-def force_answer
-  @force_answer ||= false
-end
-
+ @@ -813,25 +755,7 @@

- - - - - -
-
-
-
-10
-11
-12
-
-
# File 'lib/doing/configuration.rb', line 10
-
-def ignore_local=(value)
-  @ignore_local = value
-end
-
+ @@ -855,25 +779,7 @@

-
- - - - -
-
-
-
-8
-9
-10
-
-
# File 'lib/doing/configuration.rb', line 8
-
-def settings
-  @settings
-end
-
+ @@ -892,25 +798,7 @@

-

- - - - -
-
-
-
-160
-161
-162
-
-
# File 'lib/doing/configuration.rb', line 160
-
-def additional_configs
-  @additional_configs ||= find_local_config
-end
-
+
@@ -949,75 +837,7 @@

-

- - - - -
-
-
-
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-
-
# File 'lib/doing/configuration.rb', line 169
-
-def choose_config(create: false, local: false)
-  if local && create
-    res = File.expand_path('.doingrc')
-    FileUtils.touch(res)
-    return res
-  end
-
-  return @config_file if @force_answer
-
-  if @additional_configs&.count&.positive? || create
-    choices = [@config_file].concat(@additional_configs)
-    choices.push('Create a new .doingrc in the current directory') if create && !File.exist?('.doingrc')
-    res = Doing::Prompt.choose_from(choices.uniq.sort.reverse,
-                                    sorted: false,
-                                    prompt: 'Local configs found, select which to update > ')
-
-    raise UserCancelled, 'Cancelled' unless res
-
-    if res =~ /^Create a new/
-      res = File.expand_path('.doingrc')
-      FileUtils.touch(res)
-    end
-
-    res.strip || @config_file
-  else
-    @config_file
-  end
-end
-
+
@@ -1029,25 +849,7 @@

-

- - - - -
-
-
-
-131
-132
-133
-
-
# File 'lib/doing/configuration.rb', line 131
-
-def config_dir
-  @config_dir ||= File.join(Util.user_home, '.config', 'doing')
-end
-
+
@@ -1090,95 +892,7 @@

-

- - - - -
-
-
-
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-
-
# File 'lib/doing/configuration.rb', line 338
-
-def configure(opt = {})
-  update_deprecated_config if config_file == default_config_file
-
-  @ignore_local = opt[:ignore_local] if opt[:ignore_local]
-
-  config = read_config.clone
-
-  plugin_config = Util.deep_merge_hashes(DEFAULTS['plugins'], config['plugins'] || {})
-
-  load_plugins(plugin_config['plugin_path'])
-
-  Plugins.plugins.each do |_type, plugins|
-    plugins.each do |title, plugin|
-      plugin_config[title] = plugin[:config] if plugin[:config].good?
-      config['export_templates'][title] ||= nil if plugin[:templates] && !plugin[:templates].empty?
-    end
-  end
-
-  config = Util.deep_merge_hashes({
-                                    'plugins' => plugin_config
-                                  }, config)
-
-  config = find_deprecations(config)
-
-  if !File.exist?(config_file) || opt[:rewrite]
-    Util.write_to_file(config_file, YAML.dump(config), backup: true)
-    Doing.logger.warn('Config:', "Config file written to #{config_file}")
-  end
-
-  Hooks.trigger :post_config, self
-
-  config = local_config.deep_merge(config, { extend_existing_arrays: true, sort_merged_arrays: true }) unless @ignore_local
-  # config = Util.deep_merge_hashes(config, local_config) unless @ignore_local
-
-  Hooks.trigger :post_local_config, self
-
-  config
-end
-
+
@@ -1190,45 +904,7 @@

-

- - - - -
-
-
-
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-
-
# File 'lib/doing/configuration.rb', line 146
-
-def default_config_file
-  if File.exist?(config_dir) && !File.directory?(config_dir)
-    raise DoingRuntimeError, "#{config_dir} exists but is not a directory"
-
-  end
-
-  unless File.exist?(config_dir)
-    FileUtils.mkdir_p(config_dir)
-    Doing.logger.log_now(:warn, "Config directory created at #{config_dir}")
-  end
-
-  File.join(config_dir, 'config.yml')
-end
-
+
@@ -1267,29 +943,7 @@

-

- - - - -
-
-
-
-140
-141
-142
-143
-144
-
-
# File 'lib/doing/configuration.rb', line 140
-
-def exact_match?
-  search_settings = @settings['search']
-  matching = search_settings.fetch('matching', 'pattern').normalize_matching
-  matching == :exact
-end
-
+
@@ -1301,25 +955,7 @@

-

- - - - -
-
-
-
-198
-199
-200
-
-
# File 'lib/doing/configuration.rb', line 198
-
-def fetch(*path, default)
-  @settings.dig(*path) || default
-end
-
+
@@ -1380,27 +1016,7 @@

-

- - - - -
-
-
-
-296
-297
-298
-299
-
-
# File 'lib/doing/configuration.rb', line 296
-
-def from(user_config)
-  # Util.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys)
-  Configuration[user_config].stringify_keys.deep_merge(DEFAULTS, { extend_existing_arrays: true, sort_merged_arrays: true })
-end
-
+
@@ -1462,121 +1078,7 @@

-

- - - - -
-
-
-
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-
-
# File 'lib/doing/configuration.rb', line 212
-
-def resolve_key_path(keypath, create: false, distance: 2, exact: false)
-  cfg = @settings
-  real_path = []
-  unless keypath =~ /^[.*]?$/
-    paths = keypath.split(/[:.]/)
-    element_count = paths.count
-    while paths.length.positive? && !cfg.nil?
-      path = paths.shift
-      new_cfg = nil
-
-      if cfg.is_a?(Hash)
-        matches = if exact
-                    cfg.select { |key, _| key == path }
-                  else
-                    cfg.select { |key, _| key =~ path.to_rx(distance: distance) }
-                  end
-        if matches.count.positive?
-          shortest = matches.keys.group_by(&:length).min.last[0]
-          real_path << shortest
-          new_cfg = matches[shortest]
-        end
-      else
-        new_cfg = cfg
-      end
-
-      if new_cfg.nil?
-        return real_path if real_path[-1] == path && real_path.count == element_count
-
-        if distance < 5 && !create
-          return resolve_key_path(keypath, create: false, distance: distance + 1)
-        else
-          return nil unless create
-        end
-
-        resolved = real_path.count.positive? ? "Resolved #{real_path.join('.')}, but " : ''
-        Doing.logger.log_now(:warn, "#{resolved}#{path} is unknown")
-        new_path = [*real_path, path, *paths].compact.join('.')
-        Doing.logger.log_now(:warn, "Continuing will create the path #{new_path}")
-        res = Prompt.yn('Key path not found, create it?', default_response: true)
-        raise InvalidArgument, 'Invalid key path' unless res
-
-        real_path.push(path).concat(paths).compact!
-        Doing.logger.debug('Config:', "translated key path #{keypath} to #{real_path.join('.')}") unless keypath == real_path.join('.')
-        return real_path
-      end
-      cfg = new_cfg
-    end
-  end
-  Doing.logger.debug('Config:', "translated key path #{keypath} to #{real_path.join('.')}") unless keypath == real_path.join('.')
-  real_path
-end
-
+
@@ -1632,47 +1134,7 @@

-

- - - - -
-
-
-
-383
-384
-385
-386
-387
-388
-389
-390
-391
-392
-393
-394
-395
-396
-
-
# File 'lib/doing/configuration.rb', line 383
-
-def save_view(view, title)
-  title.downcase!
-  default_template = Doing.setting('templates.default')
-  user_config = Util.safe_load_file(config_file)
-  user_config['views'] = {} unless user_config.key?('views')
-
-  view.delete_if { |k, v| v == default_template[k] }
-
-  user_config['views'][title] = view
-  Util.write_to_file(config_file, YAML.dump(user_config), backup: true)
-  Doing.logger.warn('Config:', %(View "#{title}" saved to #{config_file}))
-  Doing.logger.info('Config:', %(to use, run `doing view #{title}`))
-  Hooks.trigger :post_config, self
-end
-
+
@@ -1694,75 +1156,7 @@

-
- - - - -
-
-
-
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-329
-330
-331
-
-
# File 'lib/doing/configuration.rb', line 304
-
-def update_deprecated_config
-  # return # Until further notice
-  return if File.exist?(default_config_file)
-
-  old_file = File.join(Util.user_home, '.doingrc')
-  return unless File.exist?(old_file)
-
-  Doing.logger.log_now(:warn, 'Deprecated:', "main config file location has changed to #{config_file}")
-  res = Prompt.yn("Move #{old_file} to new location, preserving settings?", default_response: true)
-
-  return unless res
-
-  if File.exist?(default_config_file)
-    res = Prompt.yn("#{default_config_file} already exists, overwrite it?", default_response: false)
-
-    unless res
-      @config_file = old_file
-      return
-    end
-  end
-
-  FileUtils.mv old_file, default_config_file, force: true
-  Doing.logger.log_now(:warn, 'Config:', "Config file moved to #{default_config_file}")
-  Doing.logger.log_now(:warn, 'Config:', %(If ~/.doingrc exists in the future,
-                       it will be considered a local config and its values will override the
-                       default configuration.))
-  Process.exit 0
-end
-
+

@@ -1826,43 +1220,7 @@

-

- - - - -
-
-
-
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-
-
# File 'lib/doing/configuration.rb', line 274
-
-def value_for_key(keypath = '')
-  cfg = @settings
-  real_path = ['config']
-  unless keypath =~ /^[.*]?$/
-    real_path = resolve_key_path(keypath, create: false)
-    return nil unless real_path&.count&.positive?
-
-    cfg = cfg.dig(*real_path)
-  end
-
-  cfg.nil? ? nil : { real_path[-1] => cfg }
-end
-
+ @@ -1870,7 +1228,7 @@

diff --git a/docs/doc/Doing/DayOneRenderer.html b/docs/doc/Doing/DayOneRenderer.html index 7246cb96..b13d3f36 100644 --- a/docs/doc/Doing/DayOneRenderer.html +++ b/docs/doc/Doing/DayOneRenderer.html @@ -269,29 +269,7 @@

-
- - - - -
-
-
-
-13
-14
-15
-16
-17
-
-
# File 'lib/doing/plugins/export/dayone_export.rb', line 13
-
-def initialize(page_title, items, totals)
-  @page_title = page_title
-  @items = items
-  @totals = totals
-end
-
+ @@ -320,25 +298,7 @@

-
- - - - -
-
-
-
-11
-12
-13
-
-
# File 'lib/doing/plugins/export/dayone_export.rb', line 11
-
-def items
-  @items
-end
-
+ @@ -362,25 +322,7 @@

-
- - - - -
-
-
-
-11
-12
-13
-
-
# File 'lib/doing/plugins/export/dayone_export.rb', line 11
-
-def page_title
-  @page_title
-end
-
+ @@ -404,25 +346,7 @@

-
- - - - -
-
-
-
-11
-12
-13
-
-
# File 'lib/doing/plugins/export/dayone_export.rb', line 11
-
-def totals
-  @totals
-end
-
+ @@ -441,25 +365,7 @@

-

- - - - -
-
-
-
-19
-20
-21
-
-
# File 'lib/doing/plugins/export/dayone_export.rb', line 19
-
-def get_binding
-  binding()
-end
-
+ @@ -467,7 +373,7 @@

diff --git a/docs/doc/Doing/DayoneExport.html b/docs/doc/Doing/DayoneExport.html index e71bfe09..c52c3802 100644 --- a/docs/doc/Doing/DayoneExport.html +++ b/docs/doc/Doing/DayoneExport.html @@ -236,277 +236,7 @@

-

- - - - -
-
-
-
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-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
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-
-
# File 'lib/doing/plugins/export/dayone_export.rb', line 46
-
-def self.render(wwid, items, variables: {})
-
-  return unless items.good?
-
-  config = Doing.settings
-
-  opt = variables[:options]
-  trigger = opt[:output]
-  digest = case trigger
-           when /-days?$/
-             :day
-           when /-entries$/
-             :entries
-           else
-             :digest
-           end
-
-  all_items = []
-  days = {}
-  flagged = false
-  tags = []
-
-  items.each do |i|
-    day_flagged = false
-    date_key = i.date.strftime('%Y-%m-%d')
-
-    if String.method_defined? :force_encoding
-      title = i.title.force_encoding('utf-8').link_urls(format: :markdown)
-      note = i.note.map { |line| line.force_encoding('utf-8').strip.link_urls(format: :markdown) } if i.note
-    else
-      title = i.title.link_urls(format: :markdown)
-      note = i.note.map { |line| line.strip.link_urls(format: :markdown) } if i.note
-    end
-
-    title = "#{title} @section(#{i.section})" unless variables[:is_single]
-
-    tags.concat(i.tag_array).sort!.uniq!
-    flagged = day_flagged = true if i.tags?(config['marker_tag'])
-
-    interval = wwid.get_interval(i, record: true) if i.title =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
-    interval ||= false
-    human_time = false
-    if interval
-      d, h, m = wwid.get_interval(i, formatted: false).format_time
-      human_times = []
-      human_times << format('%<d>d day%<p>s', d: d, p: d == 1 ? '' : 's') if d > 0
-      human_times << format('%<h>d hour%<p>s', h: h, p: h == 1 ? '' : 's') if h > 0
-      human_times << format('%<m>d minute%<p>s', m: m, p: m == 1 ? '' : 's') if m > 0
-      human_time = human_times.join(', ')
-    end
-
-    done = i.tags?('done') ? ' ' : ' '
-
-    item = {
-      date_object: i.date,
-      date: i.date.strftime('%a %-I:%M%p'),
-      shortdate: i.date.relative_date,
-      done: done,
-      note: note,
-      section: i.section,
-      time: interval,
-      human_time: human_time,
-      title: title.strip,
-      starred: day_flagged,
-      tags: i.tag_array
-    }
-    all_items << item
-
-
-    if days.key?(date_key)
-      days[date_key][:starred] = true if day_flagged
-      days[date_key][:tags] = days[date_key][:tags].concat(i.tag_array).sort.uniq
-      days[date_key][:entries].push(item)
-    else
-      days[date_key] ||= { tags: [], entries: [], starred: false }
-      days[date_key][:starred] = true if day_flagged
-      days[date_key][:tags] = days[date_key][:tags].concat(i.tag_array).sort.uniq
-      days[date_key][:entries].push(item)
-    end
-  end
-
-
-  template = if config['export_templates']['dayone'] && File.exist?(File.expand_path(config['export_templates']['dayone']))
-               IO.read(File.expand_path(config['export_templates']['dayone']))
-             else
-               self.template('dayone')
-             end
-
-  totals = opt[:totals] ? wwid.tag_times(format: :markdown, sort_by: opt[:sort_tags], sort_order: opt[:tag_order]) : ''
-
-  case digest
-  when :day
-    days.each do |k, hsh|
-      title = "#{k}: #{variables[:page_title]}"
-      to_dayone(template: template,
-                title: title,
-                items: hsh[:entries],
-                totals: '',
-                date: Time.parse(k),
-                tags: tags,
-                starred: hsh[:starred])
-    end
-  when :entries
-    entry_template = if config['export_templates']['dayone_entry'] && File.exist?(File.expand_path(config['export_templates']['dayone_entry']))
-                       IO.read(File.expand_path(config['export_templates']['dayone_entry']))
-                     else
-                       self.template('dayone-entry')
-                     end
-    all_items.each do |item|
-      to_dayone(template: entry_template,
-                title: '',
-                items: [item],
-                totals: '',
-                date: item[:date_object],
-                tags: item[:tags],
-                starred: item[:starred])
-    end
-  else
-    to_dayone(template: template,
-                title: variables[:page_title],
-                items: all_items,
-                totals: totals,
-                date: Time.now,
-                tags: tags,
-                starred: flagged)
-  end
-
-  @out = ''
-end
-
+
@@ -518,37 +248,7 @@

-

- - - - -
-
-
-
-27
-28
-29
-30
-31
-32
-33
-34
-35
-
-
# File 'lib/doing/plugins/export/dayone_export.rb', line 27
-
-def self.settings
-  {
-    trigger: 'day(?:one)?(?:-(?:days?|entries))?',
-    templates: [
-      { name: 'dayone', trigger: 'day(?:one)?$', format: 'erb', filename: 'dayone.erb' },
-      { name: 'dayone_entry', trigger: 'day(?:one)-entr(?:y|ies)?$', format: 'erb', filename: 'dayone-entry.erb' }
-    ]
-  }
-end
-
+
@@ -560,35 +260,7 @@

-

- - - - -
-
-
-
-37
-38
-39
-40
-41
-42
-43
-44
-
-
# File 'lib/doing/plugins/export/dayone_export.rb', line 37
-
-def self.template(trigger)
-  case trigger
-  when /day(?:one)-entr(?:y|ies)?$/
-    IO.read(File.join(File.dirname(__FILE__), '../../../templates/doing-dayone-entry.erb'))
-  else
-    IO.read(File.join(File.dirname(__FILE__), '../../../templates/doing-dayone.erb'))
-  end
-end
-
+
@@ -600,79 +272,7 @@

-

- - - - -
-
-
-
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-
-
# File 'lib/doing/plugins/export/dayone_export.rb', line 176
-
-def self.to_dayone(template: self.template(nil), title: 'doing', items: [], totals: '', date: Time.now, tags: [], starred: false)
-  mdx = DayOneRenderer.new(title, items, totals)
-
-  engine = ERB.new(template)
-  content = engine.result(mdx.get_binding)
-
-  uuid = SecureRandom.uuid
-  # uuid = `uuidgen`.strip
-
-  plist = {
-    'Creation Date' => date,
-    'Creator' => { 'Software Agent' => 'Doing/2.0.0' },
-    'Entry Text' => content,
-    'Starred' => starred,
-    'Tags' => tags.sort.uniq.delete_if { |t| t =~ /(done|cancell?ed|from)/ },
-    'UUID' => uuid
-  }
-
-  container = File.expand_path('~/Library/Group Containers/')
-  dayone_dir = Dir.glob('*.dayoneapp2', base: container).first
-  import_dir = File.join(container, dayone_dir, 'Data', 'Auto Import', 'Default Journal.dayone', 'entries')
-  FileUtils.mkdir_p(import_dir) unless File.exist?(import_dir)
-  entry_file = File.join(import_dir, "#{uuid}.doentry")
-  Doing.logger.debug('Day One Export:', "Exporting to #{entry_file}")
-  File.open(entry_file, 'w') do |f|
-    f.puts plist.to_plist
-  end
-
-  Doing.logger.count(:exported, level: :info, count: items.count, message: '%count %items exported to Day One import folder')
-end
-
+
@@ -680,7 +280,7 @@

diff --git a/docs/doc/Doing/DoingExport.html b/docs/doc/Doing/DoingExport.html index dd74702b..e4a1bf44 100644 --- a/docs/doc/Doing/DoingExport.html +++ b/docs/doc/Doing/DoingExport.html @@ -176,57 +176,7 @@

-

- - - - -
-
-
-
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-
-
# File 'lib/doing/plugins/export/doing_export.rb', line 15
-
-def self.render(wwid, items, variables: {})
-  return if items.nil?
-
-  content = Doing::Items.new
-  items.each do |item|
-    content.add_section(item.section, log: false)
-    content.push(item)
-  end
-
-  out = []
-  content.sections.each do |section|
-    out.push(section.original)
-    is = content.in_section(section.title).sort_by { |i| [i.date, i.title] }
-    is.reverse! if Doing.setting('doing_file_sort').normalize_order == :desc
-    is.each { |item| out.push(item.to_s) }
-  end
-
-  Doing::Pager.page out.join("\n")
-end
-
+
@@ -238,29 +188,7 @@

-

- - - - -
-
-
-
-9
-10
-11
-12
-13
-
-
# File 'lib/doing/plugins/export/doing_export.rb', line 9
-
-def self.settings
-  {
-    trigger: 'doing'
-  }
-end
-
+
@@ -268,7 +196,7 @@

diff --git a/docs/doc/Doing/DoingImport.html b/docs/doc/Doing/DoingImport.html index dda0b124..faf5d7f7 100644 --- a/docs/doc/Doing/DoingImport.html +++ b/docs/doc/Doing/DoingImport.html @@ -259,33 +259,7 @@

- - - - - -
-
-
-
-112
-113
-114
-115
-116
-117
-118
-
-
# File 'lib/doing/plugins/import/doing_import.rb', line 112
-
-def self.duplicate?(item)
-  @old_items.each do |oi|
-    return true if item.equal?(oi)
-  end
-
-  false
-end
-
+
@@ -375,189 +349,7 @@

-

- - - - -
-
-
-
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-
-
# File 'lib/doing/plugins/import/doing_import.rb', line 26
-
-def self.import(wwid, path, options: {})
-  exit_now! 'Path to Doing file required' if path.nil?
-
-  exit_now! 'File not found' unless File.exist?(File.expand_path(path))
-
-  options[:no_overlap] ||= false
-
-  options[:autotag] ||= Doing.auto_tag
-
-  tags = options[:tag] ? options[:tag].split(/[ ,]+/).map { |t| t.sub(/^@?/, '') } : []
-  prefix = options[:prefix] || ''
-
-  @old_items = wwid.content.dup
-
-  new_items = read_doing_file(path)
-
-  total = new_items.count
-
-  options[:count] = 0
-  new_items = wwid.filter_items(new_items, opt: options)
-
-  skipped = total - new_items.count
-  Doing.logger.debug('Skipped:', %(#{skipped} items that didn't match filter criteria)) if skipped.positive?
-
-  imported = []
-  updated = 0
-
-  new_items.each do |item|
-    next if duplicate?(item)
-
-    title = "#{prefix} #{item.title}"
-    tags.each do |tag|
-      if title =~ /\b#{tag}\b/i
-        title.sub!(/\b#{tag}\b/i, "@#{tag}")
-      else
-        title += " @#{tag}"
-      end
-    end
-    title = wwid.autotag(title) if options[:autotag]
-    title.gsub!(/ +/, ' ')
-    title.strip!
-    section = options[:section] || item.section
-    section ||= Doing.setting('current_section')
-
-    new_item = Item.new(item.date, title, section, item.note, item.id)
-
-    is_match = true
-
-    if options[:search]
-      is_match = new_item.search(options[:search], case_type: options[:case], negate: options[:not])
-    end
-
-    if is_match && options[:date_filter]
-      is_match = new_item.date > options[:date_filter][0] && new_item.date < options[:date_filter][1]
-      is_match = options[:not] ? !is_match : is_match
-    end
-
-    if wwid.content.find_id(new_item.id)
-      old_index = wwid.content.index_for_id(new_item.id)
-      old_item = wwid.content[old_index].clone
-      wwid.content[old_index] = new_item
-      Hooks.trigger :post_entry_updated, self, new_item, old_item
-      updated += 1
-    else
-      imported.push(new_item) if is_match
-    end
-  end
-
-  dups = new_items.count - imported.count
-  Doing.logger.info('Skipped:', %(#{dups} duplicate items)) if dups.positive?
-
-  imported = wwid.dedup(imported, no_overlap: options[:no_overlap])
-  overlaps = new_items.count - imported.count - dups
-  Doing.logger.debug('Skipped:', "#{overlaps} items with overlapping times") if overlaps.positive?
-
-  imported.each do |item|
-    wwid.content.add_section(item.section) unless wwid.content.section?(item.section)
-    Hooks.trigger :pre_entry_add, self, item
-    wwid.content.push(item)
-    Hooks.trigger :post_entry_added, self, item
-  end
-
-  Doing.logger.info('Updated:', %(#{updated} items))
-  Doing.logger.info('Imported:', "#{imported.count} items")
-end
-
+
@@ -569,105 +361,7 @@

-

- - - - -
-
-
-
-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
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-
-
# File 'lib/doing/plugins/import/doing_import.rb', line 120
-
-def self.read_doing_file(path)
-  doing_file = File.expand_path(path)
-
-  return nil unless File.exist?(doing_file) && File.file?(doing_file) && File.stat(doing_file).size.positive?
-
-  input = IO.read(doing_file)
-  input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
-
-  lines = input.split(/[\n\r]/)
-  current = 0
-
-  items = []
-  section = ''
-
-  lines.each do |line|
-    next if line =~ /^\s*$/
-
-    case line
-    when /^(\S[\S ]+):(\s+@[\w\-_.]+(?= |$))*\s*$/
-      section = Regexp.last_match(1)
-      current = 0
-    when /^\s*- (\d{4}-\d\d-\d\d \d\d:\d\d) \| (.*?)(?: <([a-z0-9]{32})>)? *$/
-      date = Regexp.last_match(1).strip
-      title = Regexp.last_match(2).strip
-      id = Regexp.last_match(3)
-      item = Item.new(date, title, section, nil, id)
-      items.push(item)
-      current += 1
-    when /^\S/
-      next
-    else
-      next if current.zero?
-
-      prev_item = items[current - 1]
-      prev_item.note = Note.new unless prev_item.note
-
-      prev_item.note.add(line)
-      # end
-    end
-  end
-
-  items
-end
-
+

@@ -679,29 +373,7 @@

-

- - - - -
-
-
-
-11
-12
-13
-14
-15
-
-
# File 'lib/doing/plugins/import/doing_import.rb', line 11
-
-def self.settings
-  {
-    trigger: 'doing'
-  }
-end
-
+
@@ -709,7 +381,7 @@

diff --git a/docs/doc/Doing/Entry.html b/docs/doc/Doing/Entry.html index ab73f5ec..18044662 100644 --- a/docs/doc/Doing/Entry.html +++ b/docs/doc/Doing/Entry.html @@ -329,29 +329,7 @@

-
- - - - -
-
-
-
-10
-11
-12
-13
-14
-
-
# File 'lib/doing/changelog/entry.rb', line 10
-
-def initialize(string, type, prefix: false)
-  @string = string
-  @type = type
-  @prefix = prefix
-end
-
+ @@ -399,25 +377,7 @@

- - - - - -
-
-
-
-8
-9
-10
-
-
# File 'lib/doing/changelog/entry.rb', line 8
-
-def prefix=(value)
-  @prefix = value
-end
-
+ @@ -441,25 +401,7 @@

-
- - - - -
-
-
-
-6
-7
-8
-
-
# File 'lib/doing/changelog/entry.rb', line 6
-
-def string
-  @string
-end
-
+ @@ -483,25 +425,7 @@

-
- - - - -
-
-
-
-6
-7
-8
-
-
# File 'lib/doing/changelog/entry.rb', line 6
-
-def type
-  @type
-end
-
+ @@ -520,25 +444,7 @@

-

- - - - -
-
-
-
-16
-17
-18
-
-
# File 'lib/doing/changelog/entry.rb', line 16
-
-def clean(string)
-  string.gsub(/\|/, '\|')
-end
-
+
@@ -550,25 +456,7 @@ - - - - -
-
-
-
-20
-21
-22
-
-
# File 'lib/doing/changelog/entry.rb', line 20
-
-def print_prefix
-  @prefix ? "#{@type}: " : ''
-end
-
+
@@ -580,25 +468,7 @@

-

- - - - -
-
-
-
-24
-25
-26
-
-
# File 'lib/doing/changelog/entry.rb', line 24
-
-def to_s
-  "- #{print_prefix}#{clean(@string)}"
-end
-
+
@@ -606,7 +476,7 @@

diff --git a/docs/doc/Doing/Errors.html b/docs/doc/Doing/Errors.html index 2075465e..a413ac54 100644 --- a/docs/doc/Doing/Errors.html +++ b/docs/doc/Doing/Errors.html @@ -181,7 +181,7 @@

diff --git a/docs/doc/Doing/Errors/DoingNoTraceError.html b/docs/doc/Doing/Errors/DoingNoTraceError.html index 6f818322..6f7c75f0 100644 --- a/docs/doc/Doing/Errors/DoingNoTraceError.html +++ b/docs/doc/Doing/Errors/DoingNoTraceError.html @@ -171,37 +171,7 @@

-
- - - - -
-
-
-
-6
-7
-8
-9
-10
-11
-12
-13
-14
-
-
# File 'lib/doing/errors.rb', line 6
-
-def initialize(msg = nil, level: nil, topic: 'Error:', exit_code: 1)
-  level ||= :error
-  Doing.logger.output_results
-  if msg
-    Doing.logger.log_now(level, topic, msg)
-  end
-
-  Process.exit exit_code
-end
-
+ @@ -210,7 +180,7 @@

diff --git a/docs/doc/Doing/Errors/DoingRuntimeError.html b/docs/doc/Doing/Errors/DoingRuntimeError.html index 21d1561e..45814224 100644 --- a/docs/doc/Doing/Errors/DoingRuntimeError.html +++ b/docs/doc/Doing/Errors/DoingRuntimeError.html @@ -171,31 +171,7 @@

-
- - - - -
-
-
-
-44
-45
-46
-47
-48
-49
-
-
# File 'lib/doing/errors.rb', line 44
-
-def initialize(msg = 'Runtime Error', exit_code = nil, topic: 'Error:')
-  Doing.logger.output_results
-  Doing.logger.log_now(:error, topic, msg)
-
-  Process.exit exit_code if exit_code
-end
-
+ @@ -204,7 +180,7 @@

diff --git a/docs/doc/Doing/Errors/DoingStandardError.html b/docs/doc/Doing/Errors/DoingStandardError.html index b92b581a..7ec7096c 100644 --- a/docs/doc/Doing/Errors/DoingStandardError.html +++ b/docs/doc/Doing/Errors/DoingStandardError.html @@ -167,29 +167,7 @@

-
- - - - -
-
-
-
-30
-31
-32
-33
-34
-
-
# File 'lib/doing/errors.rb', line 30
-
-def initialize(msg = '')
-  Doing.logger.output_results
-
-  super(msg)
-end
-
+ @@ -198,7 +176,7 @@

diff --git a/docs/doc/Doing/Errors/EmptyInput.html b/docs/doc/Doing/Errors/EmptyInput.html index a8b2653d..b0a00ac3 100644 --- a/docs/doc/Doing/Errors/EmptyInput.html +++ b/docs/doc/Doing/Errors/EmptyInput.html @@ -175,25 +175,7 @@

-
- - - - -
-
-
-
-24
-25
-26
-
-
# File 'lib/doing/errors.rb', line 24
-
-def initialize(msg = 'No input', topic = 'Exited:')
-  super(msg, level: :warn, topic: topic, exit_code: 6)
-end
-
+ @@ -202,7 +184,7 @@

diff --git a/docs/doc/Doing/Errors/HistoryLimitError.html b/docs/doc/Doing/Errors/HistoryLimitError.html index 2c22ea11..db4f23ea 100644 --- a/docs/doc/Doing/Errors/HistoryLimitError.html +++ b/docs/doc/Doing/Errors/HistoryLimitError.html @@ -175,25 +175,7 @@

-
- - - - -
-
-
-
-60
-61
-62
-
-
# File 'lib/doing/errors.rb', line 60
-
-def initialize(msg, exit_code = 24)
-  super(msg, level: :error, topic: 'History:', exit_code: exit_code)
-end
-
+ @@ -202,7 +184,7 @@

diff --git a/docs/doc/Doing/Errors/InvalidPlugin.html b/docs/doc/Doing/Errors/InvalidPlugin.html index 55ca3197..d466f0ab 100644 --- a/docs/doc/Doing/Errors/InvalidPlugin.html +++ b/docs/doc/Doing/Errors/InvalidPlugin.html @@ -175,25 +175,7 @@

-
- - - - -
-
-
-
-72
-73
-74
-
-
# File 'lib/doing/errors.rb', line 72
-
-def initialize(kind = 'output', msg = nil)
-  super(%(Invalid #{kind} type (#{msg})), 128, topic: 'Plugin:')
-end
-
+ @@ -202,7 +184,7 @@

diff --git a/docs/doc/Doing/Errors/MissingBackupFile.html b/docs/doc/Doing/Errors/MissingBackupFile.html index 52e2b88f..e0b39f5f 100644 --- a/docs/doc/Doing/Errors/MissingBackupFile.html +++ b/docs/doc/Doing/Errors/MissingBackupFile.html @@ -175,25 +175,7 @@

-
- - - - -
-
-
-
-66
-67
-68
-
-
# File 'lib/doing/errors.rb', line 66
-
-def initialize(msg, exit_code = 26)
-  super(msg, level: :error, topic: 'History:', exit_code: exit_code)
-end
-
+ @@ -202,7 +184,7 @@

diff --git a/docs/doc/Doing/Errors/NoResults.html b/docs/doc/Doing/Errors/NoResults.html index bba2387b..4715f5d7 100644 --- a/docs/doc/Doing/Errors/NoResults.html +++ b/docs/doc/Doing/Errors/NoResults.html @@ -175,27 +175,7 @@

-
- - - - -
-
-
-
-53
-54
-55
-56
-
-
# File 'lib/doing/errors.rb', line 53
-
-def initialize(msg = 'No results', topic = 'Exited:')
-  super(msg, level: :warn, topic: topic, exit_code: 0)
-
-end
-
+ @@ -204,7 +184,7 @@

diff --git a/docs/doc/Doing/Errors/PluginException.html b/docs/doc/Doing/Errors/PluginException.html index 88153e58..d3f2b880 100644 --- a/docs/doc/Doing/Errors/PluginException.html +++ b/docs/doc/Doing/Errors/PluginException.html @@ -200,65 +200,7 @@

-
- - - - -
-
-
-
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-100
-101
-102
-
-
# File 'lib/doing/errors.rb', line 80
-
-def initialize(msg = 'Plugin error', type = nil, plugin = nil)
-  @plugin = plugin || 'Unknown Plugin'
-
-  type ||= 'Unknown'
-  @type = case type.to_s
-          when /^i/
-            'Import plugin'
-          when /^e/
-            'Export plugin'
-          when /^h/
-            'Hook'
-          when /^u/
-            'Unrecognized'
-          else
-            type.to_s
-          end
-
-  msg = "(#{@type}: #{@plugin}) #{msg}"
-
-  Doing.logger.log_now(:error, 'Plugin:', msg)
-
-  super(msg)
-end
-
+ @@ -287,25 +229,7 @@

-
- - - - -
-
-
-
-78
-79
-80
-
-
# File 'lib/doing/errors.rb', line 78
-
-def plugin
-  @plugin
-end
-
+ @@ -314,7 +238,7 @@

diff --git a/docs/doc/Doing/Errors/UserCancelled.html b/docs/doc/Doing/Errors/UserCancelled.html index 88d9b67f..93ee73eb 100644 --- a/docs/doc/Doing/Errors/UserCancelled.html +++ b/docs/doc/Doing/Errors/UserCancelled.html @@ -175,25 +175,7 @@

-
- - - - -
-
-
-
-18
-19
-20
-
-
# File 'lib/doing/errors.rb', line 18
-
-def initialize(msg = 'Cancelled', topic = 'Exited:')
-  super(msg, level: :warn, topic: topic, exit_code: 1)
-end
-
+ @@ -202,7 +184,7 @@

diff --git a/docs/doc/Doing/Errors/WrongCommand.html b/docs/doc/Doing/Errors/WrongCommand.html index e768bc79..17c3bca8 100644 --- a/docs/doc/Doing/Errors/WrongCommand.html +++ b/docs/doc/Doing/Errors/WrongCommand.html @@ -175,25 +175,7 @@

-
- - - - -
-
-
-
-38
-39
-40
-
-
# File 'lib/doing/errors.rb', line 38
-
-def initialize(msg = 'wrong command', topic: 'Error:')
-  super(msg, level: :warn, topic: topic, exit_code: 2)
-end
-
+ @@ -202,7 +184,7 @@

diff --git a/docs/doc/Doing/HTMLExport.html b/docs/doc/Doing/HTMLExport.html index 1432cbab..149af94c 100644 --- a/docs/doc/Doing/HTMLExport.html +++ b/docs/doc/Doing/HTMLExport.html @@ -214,119 +214,7 @@

-

- - - - -
-
-
-
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-
-
# File 'lib/doing/plugins/export/html_export.rb', line 29
-
-def self.render(wwid, items, variables: {})
-  return if items.nil?
-
-  opt = variables[:options]
-
-  items_out = []
-  items.each do |i|
-    # if i.has_key?('note')
-    #   note = '<span class="note">' + i.note.map{|n| n.strip }.join('<br>') + '</span>'
-    # else
-    #   note = ''
-    # end
-    if String.method_defined? :force_encoding
-      title = i.title.force_encoding('utf-8').link_urls
-      note = i.note.map { |line| line.force_encoding('utf-8').strip.link_urls } if i.note
-    else
-      title = i.title.link_urls
-      note = i.note.map { |line| line.strip.link_urls } if i.note
-    end
-
-    interval = wwid.get_interval(i) if i.title =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
-    interval ||= false
-
-    items_out << {
-      date: i.date.strftime('%a %-I:%M%p'),
-      title: title.gsub(/(@[^ (]+(\(.*?\))?)/im, '<span class="tag">\1</span>').strip, #+ " #{note}"
-      note: note,
-      time: interval,
-      section: i.section
-    }
-  end
-
-  template = if Doing.setting('export_templates.haml') && File.exist?(File.expand_path(Doing.setting('export_templates.haml')))
-               IO.read(File.expand_path(Doing.setting('export_templates.haml')))
-             else
-               self.template('html')
-             end
-
-  style = if Doing.setting('export_templates.css') && File.exist?(File.expand_path(Doing.setting('export_templates.css')))
-            IO.read(File.expand_path(Doing.setting('export_templates.css')))
-          else
-            self.template('css')
-          end
-
-  totals = opt[:totals] ? wwid.tag_times(format: :html, sort_by: opt[:sort_tags], sort_order: opt[:tag_order]) : ''
-  engine = Haml::Engine.new(template)
-  Doing.logger.debug('HTML Export:', "#{items_out.count} items output to HTML")
-  @out = engine.render(Object.new,
-                     { :@items => items_out, :@page_title => variables[:page_title], :@style => style, :@totals => totals })
-end
-
+
@@ -338,37 +226,7 @@

-

- - - - -
-
-
-
-11
-12
-13
-14
-15
-16
-17
-18
-19
-
-
# File 'lib/doing/plugins/export/html_export.rb', line 11
-
-def self.settings
-  {
-    trigger: 'html?|web(?:page)?',
-    templates: [
-      { name: 'html', trigger: 'h[ta]ml?|web', format: 'haml', filename: 'html_export.haml' },
-      { name: 'html_style', trigger: 'css|styl(?:e|us)', format: 'css', filename: 'html_export.css' }
-    ]
-  }
-end
-
+
@@ -380,33 +238,7 @@

-

- - - - -
-
-
-
-21
-22
-23
-24
-25
-26
-27
-
-
# File 'lib/doing/plugins/export/html_export.rb', line 21
-
-def self.template(trigger)
-  if trigger =~ /^(css|sty)/
-    IO.read(File.join(File.dirname(__FILE__), '../../../templates/doing.css'))
-  else
-    IO.read(File.join(File.dirname(__FILE__), '../../../templates/doing.haml'))
-  end
-end
-
+
@@ -414,7 +246,7 @@

diff --git a/docs/doc/Doing/Hooks.html b/docs/doc/Doing/Hooks.html index 8ebabd5e..4aa696ca 100644 --- a/docs/doc/Doing/Hooks.html +++ b/docs/doc/Doing/Hooks.html @@ -255,27 +255,7 @@

-

- - - - -
-
-
-
-53
-54
-55
-56
-
-
# File 'lib/doing/hooks.rb', line 53
-
-def self.insert_hook(event, priority, &block)
-  @hook_priority[block] = [-priority, @hook_priority.size]
-  @registry[event] << block
-end
-
+
@@ -297,29 +277,7 @@

-
- - - - -
-
-
-
-34
-35
-36
-37
-38
-
-
# File 'lib/doing/hooks.rb', line 34
-
-def self.priority_value(priority)
-  return priority if priority.is_a?(Integer)
-
-  PRIORITY_MAP[priority] || DEFAULT_PRIORITY
-end
-
+

@@ -341,33 +299,7 @@

-
- - - - -
-
-
-
-25
-26
-27
-28
-29
-30
-31
-
-
# File 'lib/doing/hooks.rb', line 25
-
-def self.register(event, priority: DEFAULT_PRIORITY, &block)
-  if event.is_a?(Array)
-    event.each { |ev| register_one(ev, priority_value(priority), &block) }
-  else
-    register_one(event, priority_value(priority), &block)
-  end
-end
-
+

@@ -402,41 +334,7 @@

-

- - - - -
-
-
-
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-
-
# File 'lib/doing/hooks.rb', line 41
-
-def self.register_one(event, priority, &block)
-  unless @registry[event]
-    raise Doing::Errors::HookUnavailable.new("Invalid hook. Doing only supports #{@registry.keys.inspect}", 'hook', event)
-  end
-
-  raise Doing::Errors::PluginUncallable.new('Hooks must respond to :call', 'hook', event) unless block.respond_to? :call
-
-  Doing.logger.debug('Hook Manager:', "Registered #{event} hook") if ENV['DOING_PLUGIN_DEBUG']
-
-  insert_hook event, priority, &block
-end
-
+
@@ -448,37 +346,7 @@

-

- - - - -
-
-
-
-58
-59
-60
-61
-62
-63
-64
-65
-66
-
-
# File 'lib/doing/hooks.rb', line 58
-
-def self.trigger(event, *args)
-  hooks = @registry[event]
-  return unless hooks.good?
-
-  # sort and call hooks according to priority and load order
-  hooks.sort_by { |h| @hook_priority[h] }.each do |hook|
-    hook.call(*args)
-  end
-end
-
+
@@ -486,7 +354,7 @@

diff --git a/docs/doc/Doing/Item.html b/docs/doc/Doing/Item.html index 865d354e..56ecdbc1 100644 --- a/docs/doc/Doing/Item.html +++ b/docs/doc/Doing/Item.html @@ -597,33 +597,7 @@

- - - - - -
-
-
-
-36
-37
-38
-39
-40
-41
-42
-
-
# File 'lib/doing/item/item.rb', line 36
-
-def initialize(date, title, section, note = nil, id = nil)
-  @date = date.is_a?(Time) ? date : Time.parse(date)
-  @title = title
-  @section = section
-  @note = Note.new(note)
-  @id = id&.valid_id? ? id.strip : gen_id
-end
-
+ @@ -652,25 +626,7 @@

-
- - - - -
-
-
-
-18
-19
-20
-
-
# File 'lib/doing/item/item.rb', line 18
-
-def date
-  @date
-end
-
+ @@ -694,25 +650,7 @@

-
- - - - -
-
-
-
-18
-19
-20
-
-
# File 'lib/doing/item/item.rb', line 18
-
-def id
-  @id
-end
-
+ @@ -736,25 +674,7 @@

-
- - - - -
-
-
-
-18
-19
-20
-
-
# File 'lib/doing/item/item.rb', line 18
-
-def note
-  @note
-end
-
+ @@ -778,25 +698,7 @@

-
- - - - -
-
-
-
-18
-19
-20
-
-
# File 'lib/doing/item/item.rb', line 18
-
-def section
-  @section
-end
-
+ @@ -820,25 +722,7 @@

-
- - - - -
-
-
-
-18
-19
-20
-
-
# File 'lib/doing/item/item.rb', line 18
-
-def title
-  @title
-end
-
+ @@ -857,25 +741,7 @@

-

- - - - -
-
-
-
-123
-124
-125
-
-
# File 'lib/doing/item/item.rb', line 123
-
-def clone
-  Marshal.load(Marshal.dump(self))
-end
-
+
@@ -950,41 +816,7 @@

-

- - - - -
-
-
-
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-
-
# File 'lib/doing/item/item.rb', line 56
-
-def equal?(other, match_section: false)
-  return false if @title.strip != other.title.strip
-
-  return false if @date != other.date
-
-  return false unless @note.equal?(other.note)
-
-  return false if match_section && !@section.equal?(other.section)
-
-  true
-end
-
+
@@ -996,25 +828,7 @@

-

- - - - -
-
-
-
-44
-45
-46
-
-
# File 'lib/doing/item/item.rb', line 44
-
-def gen_id
-  Digest::MD5.hexdigest(to_s)
-end
-
+
@@ -1108,41 +922,7 @@

-

- - - - -
-
-
-
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-
-
# File 'lib/doing/item/item.rb', line 79
-
-def move_to(new_section, label: true, log: true)
-  from = @section
-
-  tag('from', rename_to: 'from', value: from, force: true) if label
-  @section = new_section
-
-  Doing.logger.count(@section == 'Archive' ? :archived : :moved) if log
-  Doing.logger.debug("#{@section == 'Archive' ? 'Archived' : 'Moved'}:",
-                     "#{@title.trunc(60)} from #{from} to #{@section}")
-  self
-end
-
+
@@ -1181,49 +961,7 @@

-

- - - - -
-
-
-
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-
-
# File 'lib/doing/item/item.rb', line 101
-
-def to_pretty(elements: %i[date title section])
-  output = []
-  elements.each do |e|
-    case e
-    when :date
-      output << format('%13s |', @date.relative_date).cyan
-    when :section
-      output << "#{magenta}(#{white(@section)}#{magenta})"
-    when :title
-      output << @title.white.highlight_tags('cyan')
-    end
-  end
-
-  output.join(' ')
-end
-
+
@@ -1245,25 +983,7 @@

-
- - - - -
-
-
-
-92
-93
-94
-
-
# File 'lib/doing/item/item.rb', line 92
-
-def to_s
-  "\t- #{@date.strftime('%Y-%m-%d %H:%M')} | #{@title} <#{@id}>#{@note.good? ? "\n#{@note}" : ''}"
-end
-
+

@@ -1271,7 +991,7 @@

diff --git a/docs/doc/Doing/ItemDates.html b/docs/doc/Doing/ItemDates.html index 06548c72..9cf23430 100644 --- a/docs/doc/Doing/ItemDates.html +++ b/docs/doc/Doing/ItemDates.html @@ -281,55 +281,7 @@

-

- - - - -
-
-
-
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-
-
# File 'lib/doing/item/dates.rb', line 35
-
-def calculate_end_date(opt)
-  if opt[:took]
-    if @date + opt[:took] > Time.now
-      @date = Time.now - opt[:took]
-      Time.now
-    else
-      @date + opt[:took]
-    end
-  elsif opt[:back]
-    if opt[:back].is_a? Integer
-      @date + opt[:back]
-    else
-      @date + (opt[:back] - @date)
-    end
-  else
-    Time.now
-  end
-end
-
+
@@ -351,33 +303,7 @@

-
- - - - -
-
-
-
-8
-9
-10
-11
-12
-13
-14
-
-
# File 'lib/doing/item/dates.rb', line 8
-
-def duration
-  return nil unless should_time? && should_finish?
-
-  return nil if @title =~ /(?<=^| )@done\b/
-
-  return Time.now - @date
-end
-
+

@@ -416,25 +342,7 @@

-

- - - - -
-
-
-
-31
-32
-33
-
-
# File 'lib/doing/item/dates.rb', line 31
-
-def end_date
-  @end_date ||= Time.parse(Regexp.last_match(1)) if @title =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/
-end
-
+
@@ -481,25 +389,7 @@

-

- - - - -
-
-
-
-94
-95
-96
-
-
# File 'lib/doing/item/dates.rb', line 94
-
-def expand_date_tags(additional_tags = nil)
-  @title.expand_date_tags(additional_tags)
-end
-
+
@@ -539,25 +429,7 @@

-

- - - - -
-
-
-
-22
-23
-24
-
-
# File 'lib/doing/item/dates.rb', line 22
-
-def interval
-  @interval ||= calc_interval
-end
-
+
@@ -616,41 +488,7 @@

-

- - - - -
-
-
-
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-
-
# File 'lib/doing/item/dates.rb', line 73
-
-def overlapping_time?(item_b)
-  return true if same_time?(item_b)
-
-  start_a = date
-  a_interval = interval
-  end_a = a_interval ? start_a + a_interval.to_i : start_a
-  start_b = item_b.date
-  b_interval = item_b.interval
-  end_b = b_interval ? start_b + b_interval.to_i : start_b
-  (start_a >= start_b && start_a <= end_b) || (end_a >= start_b && end_a <= end_b) || (start_a < start_b && end_a > end_b)
-end
-
+
@@ -708,25 +546,7 @@

-

- - - - -
-
-
-
-61
-62
-63
-
-
# File 'lib/doing/item/dates.rb', line 61
-
-def same_time?(item_b)
-  date == item_b.date ? interval == item_b.interval : false
-end
-
+ @@ -734,7 +554,7 @@

diff --git a/docs/doc/Doing/ItemQuery.html b/docs/doc/Doing/ItemQuery.html index 4e0144f7..2c7db544 100644 --- a/docs/doc/Doing/ItemQuery.html +++ b/docs/doc/Doing/ItemQuery.html @@ -268,73 +268,7 @@

-

- - - - -
-
-
-
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-
-
# File 'lib/doing/item/query.rb', line 72
-
-def highlight_search(search, distance: nil, negate: false, case_type: nil)
-  prefs = Doing.setting('search', {})
-  matching = prefs.fetch('matching', 'pattern').normalize_matching
-  distance ||= prefs.fetch('distance', 3).to_i
-  case_type ||= prefs.fetch('case', 'smart').normalize_case
-  new_note = Note.new
-
-  if search.rx? || matching == :fuzzy
-    rx = search.to_rx(distance: distance, case_type: case_type)
-    new_title = @title.gsub(rx) { |m| yellow(m) }
-    new_note.add(@note.to_s.gsub(rx) { |m| yellow(m) })
-  else
-    query = search.strip.to_phrase_query
-
-    if query[:must].nil? && query[:must_not].nil?
-      query[:must] = query[:should]
-      query[:should] = []
-    end
-    query[:must].concat(query[:should]).each do |s|
-      rx = Regexp.new(s.wildcard_to_rx, ignore_case(s, case_type))
-      new_title = @title.gsub(rx) { |m| yellow(m) }
-      new_note.add(@note.to_s.gsub(rx) { |m| yellow(m) })
-    end
-  end
-
-  Item.new(@date, new_title, @section, new_note)
-end
-
+
@@ -407,25 +341,7 @@

-

- - - - -
-
-
-
-68
-69
-70
-
-
# File 'lib/doing/item/query.rb', line 68
-
-def ignore_case(search, case_type)
-  (case_type == :smart && search !~ /[A-Z]/) || case_type == :ignore
-end
-
+
@@ -483,257 +399,7 @@

-

- - - - -
-
-
-
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-
-
# File 'lib/doing/item/query.rb', line 162
-
-def keep_item?(opt)
-  item = dup
-  time_rx = /^(\d{1,2}+(:\d{1,2}+)?( *(am|pm))?|midnight|noon)$/i
-
-  keep = true
-  if opt[:unfinished]
-    finished = item.tags?('done', :and)
-    finished = opt[:not] ? !finished : finished
-    keep = false if finished
-  end
-
-  if keep && opt[:val]&.count&.positive?
-    bool = opt[:bool].normalize_bool if opt[:bool]
-    bool ||= :and
-    bool = :and if bool == :pattern
-
-    val_match = opt[:val].nil? || opt[:val].empty? ? true : item.tag_values?(opt[:val], bool)
-    keep = false unless val_match
-    keep = opt[:not] ? !keep : keep
-  end
-
-  if keep && opt[:tag]
-    opt[:tag_bool] = opt[:bool].normalize_bool if opt[:bool]
-    opt[:tag_bool] ||= :and
-    tag_match = opt[:tag].nil? || opt[:tag].empty? ? true : item.tags?(opt[:tag], opt[:tag_bool])
-    keep = false unless tag_match
-    keep = opt[:not] ? !keep : keep
-  end
-
-  if keep && opt[:search]
-    search_match = if opt[:search].nil? || opt[:search].empty?
-                     true
-                   else
-                     item.search(opt[:search], case_type: opt[:case].normalize_case)
-                   end
-
-    keep = false unless search_match
-    keep = opt[:not] ? !keep : keep
-  end
-
-  if keep && opt[:date_filter]&.length == 2
-    start_date = opt[:date_filter][0]
-    end_date = opt[:date_filter][1]
-
-    in_date_range = if end_date
-                      item.date >= start_date && item.date <= end_date
-                    else
-                      item.date.strftime('%F') == start_date.strftime('%F')
-                    end
-    keep = false unless in_date_range
-    keep = opt[:not] ? !keep : keep
-  end
-
-  if keep && opt[:time_filter][0] || opt[:time_filter][1]
-    opt[:time_filter].map! { |v| v =~ /(12 *am|midnight)/i ? '00:00' : v }
-
-    start_string = if opt[:time_filter][0].nil?
-                     "#{item.date.strftime('%Y-%m-%d')} 00:00"
-                   else
-                     "#{item.date.strftime('%Y-%m-%d')} #{opt[:time_filter][0]}"
-                   end
-    start_time = start_string.chronify(guess: :begin)
-
-    end_string = if opt[:time_filter][1].nil?
-                   "#{item.date.to_datetime.next_day.strftime('%Y-%m-%d')} 00:00"
-                 else
-                   "#{item.date.strftime('%Y-%m-%d')} #{opt[:time_filter][1]}"
-                 end
-    end_time = end_string.chronify(guess: :end) || Time.now
-
-    in_time_range = item.date >= start_time && item.date <= end_time
-
-    keep = false unless in_time_range
-    keep = opt[:not] ? !keep : keep
-  end
-
-  keep = false if keep && opt[:only_timed] && !item.interval
-
-  if keep && opt[:tag_filter]
-    keep = item.tags?(opt[:tag_filter]['tags'], opt[:tag_filter]['bool'])
-    keep = opt[:not] ? !keep : keep
-  end
-
-  if keep && opt[:before]
-    before = opt[:before]
-    cutoff = if before.is_a?(String) && before =~ time_rx
-               "#{item.date.strftime('%Y-%m-%d')} #{before}".chronify(guess: :begin)
-             elsif before.is_a?(String)
-               before.chronify(guess: :begin)
-             else
-               before
-             end
-    keep = cutoff && item.date <= cutoff
-    keep = opt[:not] ? !keep : keep
-  end
-
-  if keep && opt[:after]
-    after = opt[:after]
-    cutoff = if after.is_a?(String) && after =~ time_rx
-               "#{item.date.strftime('%Y-%m-%d')} #{after}".chronify(guess: :end)
-             elsif after.is_a?(String)
-               after.chronify(guess: :end)
-             else
-               after
-             end
-    keep = cutoff && item.date >= cutoff
-    keep = opt[:not] ? !keep : keep
-  end
-
-  if keep && opt[:today]
-    keep = item.date >= Date.today.to_time && item.date < Date.today.next_day.to_time
-    keep = opt[:not] ? !keep : keep
-  elsif keep && opt[:yesterday]
-    keep = item.date >= Date.today.prev_day.to_time && item.date < Date.today.to_time
-    keep = opt[:not] ? !keep : keep
-  end
-
-  keep
-end
-
+
@@ -827,105 +493,7 @@

-

- - - - -
-
-
-
-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
-150
-151
-152
-153
-
-
# File 'lib/doing/item/query.rb', line 111
-
-def search(search, distance: nil, negate: false, case_type: nil)
-  prefs = Doing.setting('search', {})
-  matching = prefs.fetch('matching', 'pattern').normalize_matching
-  distance ||= prefs.fetch('distance', 3).to_i
-  case_type ||= prefs.fetch('case', 'smart').normalize_case
-
-  if search.rx? || matching == :fuzzy
-    matches = @title + @note.to_s =~ search.to_rx(distance: distance, case_type: case_type)
-  else
-    query = search.strip.to_phrase_query
-
-    if query[:must].nil? && query[:must_not].nil?
-      query[:must] = query[:should]
-      query[:should] = []
-    end
-    matches = no_searches?(query[:must_not], case_type: case_type)
-    matches &&= all_searches?(query[:must], case_type: case_type)
-    matches &&= any_searches?(query[:should], case_type: case_type)
-  end
-  # if search =~ /(?<=\A| )[+-]\S/
-  # else
-  #   text = @title + @note.to_s
-  #   matches = text =~ search.to_rx(distance: distance, case_type: case_type)
-  # end
-
-  # if search.rx? || !fuzzy
-  #   matches = text =~ search.to_rx(distance: distance, case_type: case_type)
-  # else
-  #   distance = 0.25 if distance > 1
-  #   score = if (case_type == :smart && search !~ /[A-Z]/) || case_type == :ignore
-  #             text.downcase.pair_distance_similar(search.downcase)
-  #           else
-  #             score = text.pair_distance_similar(search)
-  #           end
-
-  #   if score >= distance
-  #     matches = true
-  #     Doing.logger.debug('Fuzzy Match:', %(#{@title}, "#{search}" #{score}))
-  #   end
-  # end
-
-  negate ? !matches : matches
-end
-
+
@@ -1017,45 +585,7 @@

-

- - - - -
-
-
-
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-
-
# File 'lib/doing/item/query.rb', line 46
-
-def tag_values?(queries, bool = :and, negate: false)
-  bool = bool.normalize_bool
-
-  matches = case bool
-            when :and
-              all_values?(queries)
-            when :not
-              no_values?(queries)
-            else
-              any_values?(queries)
-            end
-  negate ? !matches : matches
-end
-
+
@@ -1147,61 +677,7 @@

-

- - - - -
-
-
-
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-
-
# File 'lib/doing/item/query.rb', line 15
-
-def tags?(tags, bool = :and, negate: false)
-  if bool == :pattern
-    tags = tags.to_tags.tags_to_array.join(' ')
-    matches = tag_pattern?(tags)
-
-    return negate ? !matches : matches
-  end
-
-  tags = split_tags(tags)
-  bool = bool.normalize_bool
-
-  matches = case bool
-            when :and
-              all_tags?(tags)
-            when :not
-              no_tags?(tags)
-            else
-              any_tags?(tags)
-            end
-  negate ? !matches : matches
-end
-
+ @@ -1209,7 +685,7 @@

diff --git a/docs/doc/Doing/ItemState.html b/docs/doc/Doing/ItemState.html index 64afad1a..ce7cf90c 100644 --- a/docs/doc/Doing/ItemState.html +++ b/docs/doc/Doing/ItemState.html @@ -250,25 +250,7 @@

- - - - - -
-
-
-
-9
-10
-11
-
-
# File 'lib/doing/item/state.rb', line 9
-
-def finished?
-  tags?('done')
-end
-
+
@@ -308,25 +290,7 @@

-

- - - - -
-
-
-
-28
-29
-30
-
-
# File 'lib/doing/item/state.rb', line 28
-
-def should_finish?
-  should?('never_finish')
-end
-
+
@@ -366,25 +330,7 @@

-

- - - - -
-
-
-
-38
-39
-40
-
-
# File 'lib/doing/item/state.rb', line 38
-
-def should_time?
-  should?('never_time')
-end
-
+
@@ -423,25 +369,7 @@

-

- - - - -
-
-
-
-18
-19
-20
-
-
# File 'lib/doing/item/state.rb', line 18
-
-def unfinished?
-  tags?('done', negate: true)
-end
-
+ @@ -449,7 +377,7 @@

diff --git a/docs/doc/Doing/ItemTags.html b/docs/doc/Doing/ItemTags.html index cc9c9e62..59721b60 100644 --- a/docs/doc/Doing/ItemTags.html +++ b/docs/doc/Doing/ItemTags.html @@ -362,83 +362,7 @@

- - - - - -
-
-
-
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-
-
# File 'lib/doing/item/tags.rb', line 20
-
-def tag(tags, **options)
-  added = []
-  removed = []
-
-  date = options.fetch(:date, false)
-  options[:value] ||= date ? Time.now.strftime('%F %R') : nil
-  options.delete(:date)
-
-  single = options.fetch(:single, false)
-  options.delete(:single)
-
-  tags = tags.to_tags if tags.is_a? ::String
-
-  remove = options.fetch(:remove, false)
-  tags.each do |tag|
-    if tag =~ /^(\S+)\((.*?)\)$/
-      m = Regexp.last_match
-      tag = m[1]
-      options[:value] ||= m[2]
-    end
-
-    bool = remove ? :and : :not
-    if tags?(tag, bool) || options[:value]
-      @title = @title.tag(tag, **options).strip
-      remove ? removed.push(tag) : added.push(tag)
-    end
-  end
-
-  Doing.logger.log_change(tags_added: added, tags_removed: removed, count: 1, item: self, single: single)
-
-  self
-end
-
+
@@ -477,25 +401,7 @@

-

- - - - -
-
-
-
-77
-78
-79
-
-
# File 'lib/doing/item/tags.rb', line 77
-
-def tag_array
-  tags.tags_to_array
-end
-
+
@@ -534,25 +440,7 @@

-

- - - - -
-
-
-
-58
-59
-60
-
-
# File 'lib/doing/item/tags.rb', line 58
-
-def tags
-  @title.scan(/(?<= |\A)@([^\s(]+)/).map { |tag| tag[0] }.sort.uniq
-end
-
+
@@ -592,25 +480,7 @@

-

- - - - -
-
-
-
-68
-69
-70
-
-
# File 'lib/doing/item/tags.rb', line 68
-
-def tags_with_values
-  @title.scan(/(?<= |\A)@([^\s(]+)(?:\((.*?)\))?/).map { |tag| [tag[0], tag[1]] }.sort.uniq
-end
-
+ @@ -618,7 +488,7 @@

diff --git a/docs/doc/Doing/Items.html b/docs/doc/Doing/Items.html index 4e92f5b1..1c4339ba 100644 --- a/docs/doc/Doing/Items.html +++ b/docs/doc/Doing/Items.html @@ -692,27 +692,7 @@

-
- - - - -
-
-
-
-13
-14
-15
-16
-
-
# File 'lib/doing/items/items.rb', line 13
-
-def initialize
-  super
-  @sections = []
-end
-
+ @@ -741,25 +721,7 @@

-
- - - - -
-
-
-
-11
-12
-13
-
-
# File 'lib/doing/items/items.rb', line 11
-
-def sections
-  @sections
-end
-
+ @@ -847,35 +809,7 @@

- - - - - -
-
-
-
-59
-60
-61
-62
-63
-64
-65
-66
-
-
# File 'lib/doing/items/sections.rb', line 59
-
-def add_section(section, log: false)
-  section = section.is_a?(Section) ? section : Section.new(section.cap_first)
-
-  return if section?(section)
-
-  @sections.push(section)
-  Doing.logger.info('New section:', %("#{section}" added)) if log
-end
-
+
@@ -914,29 +848,7 @@

-

- - - - -
-
-
-
-26
-27
-28
-29
-30
-
-
# File 'lib/doing/items/util.rb', line 26
-
-def all_tags
-  each_with_object([]) do |entry, tags|
-    tags.concat(entry.tags).sort!.uniq!
-  end
-end
-
+
@@ -1013,29 +925,7 @@

-

- - - - -
-
-
-
-62
-63
-64
-65
-66
-
-
# File 'lib/doing/items/filter.rb', line 62
-
-def between_dates(start, finish)
-  start = start.chronify(guess: :begin, future: false) if start.is_a?(String)
-  finish = finish.chronify(guess: :end) if finish.is_a?(String)
-  WWID.new.filter_items(self, opt: { date_filter: [start, finish] })
-end
-
+
@@ -1074,35 +964,7 @@

-

- - - - -
-
-
-
-60
-61
-62
-63
-64
-65
-66
-67
-
-
# File 'lib/doing/items/util.rb', line 60
-
-def dedup(match_section: true)
-  unique = Items.new
-  each do |item|
-    unique.push(item) unless unique.include?(item, match_section: match_section)
-  end
-
-  unique
-end
-
+
@@ -1130,25 +992,7 @@

-

- - - - -
-
-
-
-70
-71
-72
-
-
# File 'lib/doing/items/util.rb', line 70
-
-def dedup!(match_section: true)
-  replace dedup(match_section: match_section)
-end
-
+
@@ -1174,39 +1018,7 @@

Create a deep copy of Items

-
- - - - -
-
-
-
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-
-
# File 'lib/doing/items/util.rb', line 10
-
-def delete(item)
-  deleted = nil
-  each_with_index do |i, idx|
-    if i.equal?(item, match_section: true)
-      deleted = delete_at(idx)
-      break
-    end
-  end
-  deleted
-end
-
+
@@ -1247,31 +1059,7 @@

-

- - - - -
-
-
-
-10
-11
-12
-13
-14
-15
-
-
# File 'lib/doing/items/modify.rb', line 10
-
-def delete_item(item, single: false)
-  deleted = delete(item)
-  Doing.logger.count(:deleted)
-  Doing.logger.info('Entry deleted:', deleted.title) if single
-  deleted
-end
-
+
@@ -1305,47 +1093,7 @@

-

- - - - -
-
-
-
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-
-
# File 'lib/doing/items/sections.rb', line 68
-
-def delete_section(section, log: false)
-  return unless section?(section)
-
-  raise DoingRuntimeError, 'Section not empty' if in_section(section).count.positive?
-
-  @sections.each do |sect|
-    next unless sect.title == section && in_section(sect).count.zero?
-
-    @sections.delete(sect)
-    Doing.logger.info('Removed section:', %("#{section}" removed)) if log
-  end
-
-  Doing.logger.error('Not found:', %("#{section}" not found))
-end
-
+
@@ -1404,47 +1152,7 @@

-

- - - - -
-
-
-
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-
-
# File 'lib/doing/items/util.rb', line 40
-
-def diff(items)
-  a = clone
-  b = items.clone
-
-  a.delete_if do |item|
-    if b.include?(item)
-      b.delete(item)
-      true
-    else
-      false
-    end
-  end
-  { added: b, deleted: a }
-end
-
+
@@ -1485,25 +1193,7 @@

-

- - - - -
-
-
-
-42
-43
-44
-
-
# File 'lib/doing/items/items.rb', line 42
-
-def find_id(id)
-  select { |item| item.id == id }[0]
-end
-
+
@@ -1578,45 +1268,7 @@

-

- - - - -
-
-
-
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-
-
# File 'lib/doing/items/sections.rb', line 32
-
-def guess_section(frag, distance: 2)
-  section = nil
-  re = frag.to_rx(distance: distance, case_type: :ignore)
-  @sections.each do |sect|
-    next unless sect.title =~ /#{re}/i
-
-    Doing.logger.debug('Match:', %(Assuming "#{sect.title}" from "#{frag}"))
-    section = sect
-    break
-  end
-
-  section
-end
-
+
@@ -1675,39 +1327,7 @@

-

- - - - -
-
-
-
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-
-
# File 'lib/doing/items/filter.rb', line 12
-
-def in_section(section)
-  sect = section.is_a?(Section) ? section.title : section
-  if sect =~ /^all$/i
-    dup
-  else
-    items = Items.new.concat(select { |item| !item.nil? && item.section == section })
-    items.add_section(section, log: false)
-    items
-  end
-end
-
+
@@ -1782,41 +1402,7 @@

-

- - - - -
-
-
-
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-
-
# File 'lib/doing/items/items.rb', line 26
-
-def include?(item, match_section: true)
-  includes = false
-  each do |other_item|
-    if other_item.equal?(item, match_section: match_section)
-      includes = true
-      break
-    end
-  end
-
-  includes
-end
-
+
@@ -1857,39 +1443,7 @@

-

- - - - -
-
-
-
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-
-
# File 'lib/doing/items/items.rb', line 51
-
-def index_for_id(id)
-  i = nil
-  each_with_index do |item, idx|
-    if item.id == id
-      i = idx
-      break
-    end
-  end
-  i
-end
-
+
@@ -1965,25 +1519,7 @@

-

- - - - -
-
-
-
-32
-33
-34
-
-
# File 'lib/doing/items/filter.rb', line 32
-
-def search(query, case_type: :smart)
-  WWID.new.fuzzy_filter_items(self, query, case_type: case_type)
-end
-
+
@@ -2041,27 +1577,7 @@

-

- - - - -
-
-
-
-19
-20
-21
-22
-
-
# File 'lib/doing/items/sections.rb', line 19
-
-def section?(section)
-  section = section.is_a?(Section) ? section.title.downcase : section.downcase
-  @sections.map { |i| i.title.downcase }.include?(section)
-end
-
+
@@ -2100,25 +1616,7 @@

-

- - - - -
-
-
-
-9
-10
-11
-
-
# File 'lib/doing/items/sections.rb', line 9
-
-def section_titles
-  @sections.map(&:title)
-end
-
+
@@ -2195,25 +1693,7 @@

-

- - - - -
-
-
-
-46
-47
-48
-
-
# File 'lib/doing/items/filter.rb', line 46
-
-def tagged(tags, bool: :and)
-  WWID.new.filter_items(self, opt: { tag: tags, bool: bool })
-end
-
+
@@ -2235,41 +1715,7 @@

-
- - - - -
-
-
-
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-
-
# File 'lib/doing/items/items.rb', line 63
-
-def to_s
-  out = []
-  @sections.each do |section|
-    out.push(section.original)
-    items = in_section(section.title).sort_by { |i| [i.date, i.title] }
-    items.reverse! if Doing.setting('doing_file_sort').normalize_order == :desc
-    items.each { |item| out.push(item.to_s) }
-  end
-
-  out.join("\n")
-end
-
+

@@ -2338,43 +1784,7 @@

-

- - - - -
-
-
-
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-
-
# File 'lib/doing/items/modify.rb', line 23
-
-def update_item(old_item, new_item)
-  s_idx = index { |item| item.equal?(old_item) }
-
-  raise ItemNotFound, 'Unable to find item in index, did it mutate?' unless s_idx
-
-  return if fetch(s_idx).equal?(new_item)
-
-  self[s_idx] = new_item
-  Doing.logger.count(:updated)
-  Doing.logger.info('Entry updated:', self[s_idx].title.trunc(60))
-  new_item
-end
-
+ @@ -2382,7 +1792,7 @@

diff --git a/docs/doc/Doing/JSONExport.html b/docs/doc/Doing/JSONExport.html index f2fd06a0..88513ba3 100644 --- a/docs/doc/Doing/JSONExport.html +++ b/docs/doc/Doing/JSONExport.html @@ -192,283 +192,7 @@

-

- - - - -
-
-
-
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-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
-
-
# File 'lib/doing/plugins/export/json_export.rb', line 17
-
-def self.render(wwid, items, variables: {})
-  if items.nil? || items.empty?
-    return case variables[:options][:output]
-           when 'json'
-             {
-               'section' => '',
-               'items' => [],
-               'timers' => ""
-             }.to_json
-           when 'timeline'
-            "<html></html>"
-           end
-  end
-
-  opt = variables[:options]
-  opt[:output] =  case opt[:output]
-                  when /^t/
-                    'timeline'
-                  else
-                    'json'
-                  end
-  items_out = []
-
-  last_date = items[-1].date + (60 * 60 * 24)
-  max = last_date.strftime('%F')
-  min = items[0].date.strftime('%F')
-  items.each_with_index do |i, index|
-    title = i.title.utf8
-    note = i.note.utf8
-
-    end_date = i.end_date || ''
-    interval = wwid.get_interval(i, formatted: false) || 0
-    duration = i.duration || 0
-    note ||= ''
-
-    tags = []
-    attributes = {}
-    skip_tags = %w[meanwhile done cancelled flagged]
-    i.title.scan(/@([^(\s]+)(?:\((.*?)\))?/).each do |tag|
-      tags.push(tag[0]) unless skip_tags.include?(tag[0])
-      attributes[tag[0]] = tag[1] if tag[1]
-    end
-
-    case opt[:output]
-    when 'json'
-      i = {
-        date: i.date,
-        end_date: end_date,
-        title: title.strip, #+ " #{note}"
-        section: i.section,
-        note: note.to_s(prefix: ''),
-        time: interval.time_string(format: :clock),
-        duration: duration.time_string(format: :clock),
-        tags: tags,
-        id: i.id
-      }
-
-      attributes.each { |attr, val| i[attr.to_sym] = val }
-
-      items_out << i
-
-    when 'timeline'
-      new_item = {
-        'id' => index + 1,
-        'content' => title.strip, #+ " #{note}"
-        'title' => title.strip + " (#{interval.time_string(format: :clock)})",
-        'start' => i.date.strftime('%F %T'),
-        'type' => 'box',
-        'style' => 'color:#4c566b;background-color:#d8dee9;'
-      }
-
-      if interval.to_i&.positive?
-        new_item['end'] = end_date.strftime('%F %T')
-        if interval.to_i > 3600
-          new_item['type'] = 'range'
-          new_item['style'] = 'color:white;background-color:#a2bf8a;'
-        end
-      end
-      new_item['style'] = 'color:white;background-color:#f7921e;' if i.tags?(Doing.setting('marker_tag'))
-      items_out.push(new_item)
-    end
-  end
-  case opt[:output]
-  when 'json'
-    Doing.logger.debug('JSON Export:', "#{items_out.count} items output to JSON")
-    JSON.pretty_generate({
-                           'section' => variables[:page_title],
-                           'items' => items_out,
-                           'timers' => wwid.tag_times(format: :json,
-                                                      sort_by: opt[:sort_tags],
-                                                      sort_order: opt[:tag_order])
-                         })
-  when 'timeline'
-    template = <<~EOTEMPLATE
-                <!doctype html>
-                <html>
-                <head>
-                  <link href="https://unpkg.com/vis-timeline@7.4.9/dist/vis-timeline-graph2d.min.css" rel="stylesheet" type="text/css" />
-                  <script src="https://unpkg.com/vis-timeline@7.4.9/dist/vis-timeline-graph2d.min.js"></script>
-                </head>
-                <body>
-                  <div id="mytimeline"></div>
-      #{'          '}
-                  <script type="text/javascript">
-                    // DOM element where the Timeline will be attached
-                    var container = document.getElementById('mytimeline');
-      #{'          '}
-                    // Create a DataSet with data (enables two way data binding)
-                    var data = new vis.DataSet(#{items_out.to_json});
-      #{'          '}
-                    // Configuration for the Timeline
-                    var options = {
-                      width: '100%',
-                      height: '800px',
-                      margin: {
-                        item: 20
-                      },
-                      stack: true,
-                      min: '#{min}',
-                      max: '#{max}'
-                    };
-      #{'          '}
-                    // Create a Timeline
-                    var timeline = new vis.Timeline(container, data, options);
-                  </script>
-                </body>
-                </html>
-    EOTEMPLATE
-    Doing.logger.debug('Timeline Export:', "#{items_out.count} items output to Timeline")
-    template
-  end
-end
-
+
@@ -480,29 +204,7 @@

-

- - - - -
-
-
-
-11
-12
-13
-14
-15
-
-
# File 'lib/doing/plugins/export/json_export.rb', line 11
-
-def self.settings
-  {
-    trigger: 'json|time(?:line)?'
-  }
-end
-
+
@@ -510,7 +212,7 @@

diff --git a/docs/doc/Doing/JSONImport.html b/docs/doc/Doing/JSONImport.html index 811b88ee..83a3617d 100644 --- a/docs/doc/Doing/JSONImport.html +++ b/docs/doc/Doing/JSONImport.html @@ -265,149 +265,7 @@

- - - - - -
-
-
-
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-
-
# File 'lib/doing/plugins/import/json_import.rb', line 26
-
-def self.import(wwid, path, options: {})
-  exit_now! 'Path to JSON export required' if path.nil?
-  options[:no_overlap] ||= false
-  options[:autotag] ||= Doing.auto_tag
-
-  exit_now! 'File not found' unless File.exist?(File.expand_path(path))
-
-  updated = 0
-  added = 0
-  skipped = 0
-
-  data = JSON.parse(IO.read(File.expand_path(path)))
-  new_items = []
-  new_section = options[:section] || Doing.setting('current_section')
-
-  data['items'].each do |entry|
-    title = entry['title']
-    date = Time.parse(entry['date'])
-    date ||= entry['date'].chronify
-    note = Doing::Note.new(entry['note'])
-    section = if entry['section'].empty?
-                new_section
-              else
-                entry['section']
-              end
-    id = entry.key?('id') ? entry['id'] : nil
-
-    new_item = Doing::Item.new(date, title, section, note, id)
-
-    is_match = true
-
-    if options[:search]
-      is_match = new_item.search(options[:search], case_type: options[:case], negate: options[:not])
-    end
-
-    if is_match && options[:date_filter]
-      is_match = start_time > options[:date_filter][0] && start_time < options[:date_filter][1]
-      is_match = options[:not] ? !is_match : is_match
-    end
-
-    unless is_match
-      skipped += 1
-      next
-
-    end
-
-    if wwid.content.find_id(new_item.id)
-      old_index = wwid.content.index_for_id(entry['id'])
-      old_item = wwid.content[old_index].clone
-      wwid.content[old_index] = new_item
-      Hooks.trigger :post_entry_updated, self, new_item, old_item
-      updated += 1
-    else
-      Hooks.trigger :pre_entry_add, self, item
-      wwid.content << new_entry
-      Hooks.trigger :post_entry_added, self, item
-      added += 1
-    end
-  end
-  total = new_items.count
-  skipped = data.count - total
-  Doing.logger.debug('Skipped:', %(#{skipped} items)) if skipped.positive?
-  Doing.logger.info('Updated:', %(#{updated} items))
-  Doing.logger.info('Imported:', %(#{added} new items to #{new_section}))
-end
-
+
@@ -419,29 +277,7 @@

-

- - - - -
-
-
-
-12
-13
-14
-15
-16
-
-
# File 'lib/doing/plugins/import/json_import.rb', line 12
-
-def self.settings
-  {
-    trigger: 'json'
-  }
-end
-
+

@@ -449,7 +285,7 @@

diff --git a/docs/doc/Doing/Logger.html b/docs/doc/Doing/Logger.html index b272a1d3..b3065bdf 100644 --- a/docs/doc/Doing/Logger.html +++ b/docs/doc/Doing/Logger.html @@ -771,39 +771,7 @@

- - - - - -
-
-
-
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-
-
# File 'lib/doing/logger.rb', line 49
-
-def initialize(level = :info)
-  @messages = []
-  @counters = {}
-  COUNT_KEYS.each { |key| @counters[key] = { tag: [], count: 0 } }
-  @results = []
-  @logdev = $stderr
-  @max_length = TTY::Screen.columns - 5 || 85
-  self.log_level = level
-  @prev_level = level
-end
-
+ @@ -832,25 +800,7 @@

-
- - - - -
-
-
-
-15
-16
-17
-
-
# File 'lib/doing/logger.rb', line 15
-
-def level
-  @level
-end
-
+ @@ -874,25 +824,7 @@

-
- - - - -
-
-
-
-9
-10
-11
-
-
# File 'lib/doing/logger.rb', line 9
-
-def logdev=(value)
-  @logdev = value
-end
-
+ @@ -916,25 +848,7 @@

-
- - - - -
-
-
-
-12
-13
-14
-
-
# File 'lib/doing/logger.rb', line 12
-
-def max_length=(value)
-  @max_length = value
-end
-
+ @@ -958,25 +872,7 @@

-
- - - - -
-
-
-
-17
-18
-19
-
-
# File 'lib/doing/logger.rb', line 17
-
-def messages
-  @messages
-end
-
+ @@ -1000,25 +896,7 @@

-
- - - - -
-
-
-
-17
-18
-19
-
-
# File 'lib/doing/logger.rb', line 17
-
-def results
-  @results
-end
-
+ @@ -1104,27 +982,7 @@

- - - - - -
-
-
-
-187
-188
-189
-190
-
-
# File 'lib/doing/logger.rb', line 187
-
-def abort_with(topic, message = nil, &block)
-  error(topic, message, &block)
-  abort
-end
-
+
@@ -1136,41 +994,7 @@

-

- - - - -
-
-
-
-100
-101
-102
-103
-104
-105
-106
-107
-108
-109
-110
-
-
# File 'lib/doing/logger.rb', line 100
-
-def adjust_verbosity(options = {})
-  if options[:log_level]
-    self.log_level = options[:log_level].to_sym
-  elsif options[:quiet]
-    self.log_level = :error
-  elsif options[:verbose] || options[:debug]
-    self.log_level = :debug
-  end
-  log_now :debug, 'Logging at level:', @level.to_s
-  # log_now :debug, 'Doing Version:', Doing::VERSION
-end
-
+

@@ -1182,33 +1006,7 @@

-

- - - - -
-
-
-
-270
-271
-272
-273
-274
-275
-276
-
-
# File 'lib/doing/logger.rb', line 270
-
-def benchmark(key, state)
-  return unless ENV['DOING_BENCHMARK']
-
-  @benchmarks ||= {}
-  @benchmarks[key] ||= { start: nil, finish: nil }
-  @benchmarks[key][state] = Process.clock_gettime(Process::CLOCK_MONOTONIC)
-end
-
+
@@ -1242,35 +1040,7 @@

-

- - - - -
-
-
-
-112
-113
-114
-115
-116
-117
-118
-119
-
-
# File 'lib/doing/logger.rb', line 112
-
-def count(key, level: :info, count: 1, tag: nil, message: nil)
-  raise ArgumentError, 'invalid counter key' unless COUNT_KEYS.include?(key)
-
-  @counters[key][:count] += count
-  @counters[key][:tag].concat(tag).sort.uniq unless tag.nil?
-  @counters[key][:level] ||= level
-  @counters[key][:message] ||= message
-end
-
+
@@ -1345,25 +1115,7 @@

-

- - - - -
-
-
-
-129
-130
-131
-
-
# File 'lib/doing/logger.rb', line 129
-
-def debug(topic, message = nil, &block)
-  write(:debug, topic, message, &block)
-end
-
+
@@ -1440,25 +1192,7 @@

-

- - - - -
-
-
-
-171
-172
-173
-
-
# File 'lib/doing/logger.rb', line 171
-
-def error(topic, message = nil, &block)
-  write(:error, topic, message, &block)
-end
-
+
@@ -1535,37 +1269,7 @@

-

- - - - -
-
-
-
-202
-203
-204
-205
-206
-207
-208
-209
-210
-
-
# File 'lib/doing/logger.rb', line 202
-
-def formatted_topic(topic, colon: false)
-  if colon
-    "#{topic}: ".rjust(TOPIC_WIDTH)
-  elsif topic =~ /:$/
-    "#{topic} ".rjust(TOPIC_WIDTH)
-  else
-    "#{topic} "
-  end
-end
-
+
@@ -1642,25 +1346,7 @@

-

- - - - -
-
-
-
-143
-144
-145
-
-
# File 'lib/doing/logger.rb', line 143
-
-def info(topic, message = nil, &block)
-  write(:info, topic, message, &block)
-end
-
+
@@ -1672,115 +1358,7 @@

-

- - - - -
-
-
-
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-325
-
-
# File 'lib/doing/logger.rb', line 278
-
-def log_benchmarks
-  if ENV['DOING_BENCHMARK']
-
-    output = []
-    beginning = @benchmarks[:total][:start]
-    ending = @benchmarks[:total][:finish]
-    total = ending - beginning
-    factor = TTY::Screen.columns / total
-
-    cols = Array.new(TTY::Screen.columns)
-
-    colors = %w[bgred bggreen bgyellow bgblue bgmagenta bgcyan bgwhite boldbgred boldbggreen boldbgyellow boldbgblue boldbgwhite]
-    idx = 0
-    # @benchmarks.delete(:total)
-
-    @benchmarks.sort_by { |_, timers| [timers[:start], timers[:finish]] }.each do |k, timers|
-      if timers[:finish] && timers[:start]
-        color = colors[idx % colors.count]
-        fg = if idx < 7
-               Color.boldblack
-             else
-               Color.boldwhite
-             end
-        color = Color.send(color) + fg
-
-        start = ((timers[:start] - beginning) * factor).floor
-        finish = ((timers[:finish] - beginning) * factor).ceil
-
-        cols.fill("#{color}-", start..finish)
-        cols[start] = "#{color}|"
-        cols[finish] = "#{color}|"
-        output << "#{color}#{k}#{Color.default}: #{timers[:finish] - timers[:start]}"
-      else
-        output << "#{k}: error"
-      end
-
-      idx += 1
-    end
-
-    output.each do |msg|
-      $stdout.puts color_message(:debug, 'Benchmark:', msg)
-    end
-
-    $stdout.puts color_message(:debug, 'Benchmark:', "Total: #{total}")
-
-    $stdout.puts cols[0..TTY::Screen.columns-1].join + Color.reset
-  end
-end
-
+
@@ -1792,81 +1370,7 @@

-

- - - - -
-
-
-
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-
-
# File 'lib/doing/logger.rb', line 327
-
-def log_change(tags_added: [], tags_removed: [], count: 1, item: nil, single: false)
-  if tags_added.empty? && tags_removed.empty?
-    count(:skipped, level: :debug, message: '%count %items with no change', count: count)
-  else
-    if tags_added.empty?
-      count(:skipped, level: :debug, message: 'no tags added to %count %items')
-    elsif single && item
-      elapsed = if item && tags_added.include?('done')
-                  item.interval ? " (#{item.interval&.time_string(format: :dhm)})" : ''
-                else
-                  ''
-                end
-
-      added = tags_added.log_tags
-      info('Tagged:',
-           %(added #{tags_added.count == 1 ? 'tag' : 'tags'} #{added}#{elapsed} to #{item.title}))
-    else
-      count(:added_tags, level: :info, tag: tags_added, message: '%tags added to %count %items')
-    end
-
-    if tags_removed.empty?
-      count(:skipped, level: :debug, message: 'no tags removed from %count %items')
-    elsif single && item
-      removed = tags_removed.log_tags
-      info('Untagged:',
-           %(removed #{tags_removed.count == 1 ? 'tag' : 'tags'} #{removed} from #{item.title}))
-    else
-      count(:removed_tags, level: :info, tag: tags_removed, message: '%tags removed from %count %items')
-    end
-  end
-end
-
+
@@ -1926,51 +1430,7 @@

-

- - - - -
-
-
-
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-
-
# File 'lib/doing/logger.rb', line 67
-
-def log_level=(level = 'info')
-  level = level.to_s
-
-  level = case level
-          when /^[e0]/i
-            :error
-          when /^[w1]/i
-            :warn
-          when /^[d3]/i
-            :debug
-          else
-            :info
-          end
-
-  @level = level
-end
-
+
@@ -2058,37 +1518,7 @@

-

- - - - -
-
-
-
-241
-242
-243
-244
-245
-246
-247
-248
-249
-
-
# File 'lib/doing/logger.rb', line 241
-
-def log_now(level, topic, message = nil, &block)
-  return false unless write_message?(level)
-
-  if @logdev == $stdout
-    @logdev.puts message(topic, message, &block)
-  else
-    @logdev.puts color_message(level, topic, message, &block)
-  end
-end
-
+
@@ -2127,45 +1557,7 @@

-

- - - - -
-
-
-
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-
-
# File 'lib/doing/logger.rb', line 256
-
-def output_results
-  total_counters
-  results = @results.select { |msg| write_message?(msg[:level]) }.uniq
-
-  if @logdev == $stdout
-    $stdout.print results.map { |res| res[:message].uncolor }.join("\n")
-    $stdout.puts
-  else
-    results.each do |msg|
-      @logdev.puts color_message(msg[:level], msg[:message])
-    end
-  end
-end
-
+
@@ -2187,31 +1579,7 @@

-
- - - - -
-
-
-
-93
-94
-95
-96
-97
-98
-
-
# File 'lib/doing/logger.rb', line 93
-
-def restore_level
-  return if @prev_level.nil? || @prev_level == @log_level
-
-  self.log_level = @prev_level
-  @prev_level = nil
-end
-
+

@@ -2233,31 +1601,7 @@

-
- - - - -
-
-
-
-85
-86
-87
-88
-89
-90
-
-
# File 'lib/doing/logger.rb', line 85
-
-def temp_level(level)
-  return if level.nil? || level.to_sym == @log_level
-
-  @prev_level = log_level.dup
-  @log_level = level.to_sym
-end
-
+

@@ -2334,25 +1678,7 @@

-

- - - - -
-
-
-
-157
-158
-159
-
-
# File 'lib/doing/logger.rb', line 157
-
-def warn(topic, message = nil, &block)
-  write(:warn, topic, message, &block)
-end
-
+
@@ -2463,27 +1789,7 @@

-

- - - - -
-
-
-
-228
-229
-230
-231
-
-
# File 'lib/doing/logger.rb', line 228
-
-def write(level_of_message, topic, message = nil, &block)
-  @results << { level: level_of_message, message: message(topic, message, &block) }
-  true
-end
-
+ @@ -2491,7 +1797,7 @@

diff --git a/docs/doc/Doing/MarkdownExport.html b/docs/doc/Doing/MarkdownExport.html index cf7862eb..5869d6bd 100644 --- a/docs/doc/Doing/MarkdownExport.html +++ b/docs/doc/Doing/MarkdownExport.html @@ -224,117 +224,7 @@

-

- - - - -
-
-
-
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-
-
# File 'lib/doing/plugins/export/markdown_export.rb', line 38
-
-def self.render(wwid, items, variables: {})
-  return if items.nil?
-
-  opt = variables[:options]
-
-  all_items = []
-  items.each do |i|
-    if String.method_defined? :force_encoding
-      title = i.title.force_encoding('utf-8').link_urls(format: :markdown)
-      note = i.note.map { |line| line.force_encoding('utf-8').strip.link_urls(format: :markdown) } if i.note
-    else
-      title = i.title.link_urls(format: :markdown)
-      note = i.note.map { |line| line.strip.link_urls(format: :markdown) } if i.note
-    end
-
-    title = "#{title} @section(#{i.section})" unless variables[:is_single]
-
-    interval = wwid.get_interval(i, record: true) if i.title =~ /@done\((\d{4}-\d\d-\d\d \d\d:\d\d.*?)\)/ && opt[:times]
-    interval ||= false
-
-    finished = i.title =~ /(?<= |^)@done/ ? true : false
-    done = finished ? 'x' : ' '
-
-    all_items << {
-      date: i.date.strftime('%a %-I:%M%p'),
-      shortdate: i.date.relative_date,
-      flagged: i.title =~ /(?<= |^)@#{Doing.setting('marker_tag')}/,
-      done: done,
-      finished: finished,
-      note: note,
-      section: i.section,
-      time: interval,
-      title: title.strip
-    }
-  end
-
-  template = if Doing.setting('export_templates.markdown') && File.exist?(File.expand_path(Doing.setting('export_templates.markdown')))
-               IO.read(File.expand_path(Doing.setting('export_templates.markdown')))
-             else
-               self.template(nil)
-             end
-
-  totals = opt[:totals] ? wwid.tag_times(format: :markdown, sort_by: opt[:sort_tags], sort_order: opt[:tag_order]) : ''
-
-  mdx = MarkdownRenderer.new(variables[:page_title], all_items, totals)
-  Doing.logger.debug('Markdown Export:', "#{all_items.count} items output to Markdown")
-  engine = ERB.new(template)
-  @out = engine.result(mdx.get_binding)
-end
-
+
@@ -346,31 +236,7 @@

-

- - - - -
-
-
-
-27
-28
-29
-30
-31
-32
-
-
# File 'lib/doing/plugins/export/markdown_export.rb', line 27
-
-def self.settings
-  {
-    trigger: 'markdown|mk?d|gfm',
-    templates: [{ name: 'markdown', trigger: 'mk?d|markdown', format: 'erb', filename: 'doing-markdown.erb' }]
-  }
-end
-
+
@@ -382,25 +248,7 @@

-

- - - - -
-
-
-
-34
-35
-36
-
-
# File 'lib/doing/plugins/export/markdown_export.rb', line 34
-
-def self.template(_trigger)
-  IO.read(File.join(File.dirname(__FILE__), '../../../templates/doing-markdown.erb'))
-end
-
+
@@ -408,7 +256,7 @@

diff --git a/docs/doc/Doing/Note.html b/docs/doc/Doing/Note.html index dde4c8ae..64a0381f 100644 --- a/docs/doc/Doing/Note.html +++ b/docs/doc/Doing/Note.html @@ -405,29 +405,7 @@

- - - - - -
-
-
-
-14
-15
-16
-17
-18
-
-
# File 'lib/doing/note.rb', line 14
-
-def initialize(note = [])
-  super()
-
-  add(note) if note
-end
-
+ @@ -494,37 +472,7 @@

- - - - - -
-
-
-
-28
-29
-30
-31
-32
-33
-34
-35
-36
-
-
# File 'lib/doing/note.rb', line 28
-
-def add(note, replace: false)
-  clear if replace
-  case note
-  when String
-    append_string(note)
-  when Array
-    append(note)
-  end
-end
-
+
@@ -563,25 +511,7 @@

-

- - - - -
-
-
-
-43
-44
-45
-
-
# File 'lib/doing/note.rb', line 43
-
-def compress
-  delete_if { |l| l =~ /^\s*$/ || l =~ /^#/ }
-end
-
+
@@ -593,25 +523,7 @@

-

- - - - -
-
-
-
-47
-48
-49
-
-
# File 'lib/doing/note.rb', line 47
-
-def compress!
-  replace compress
-end
-
+

@@ -670,29 +582,7 @@

-

- - - - -
-
-
-
-99
-100
-101
-102
-103
-
-
# File 'lib/doing/note.rb', line 99
-
-def equal?(other)
-  return false unless other.is_a?(Note)
-
-  to_s == other.to_s
-end
-
+
@@ -732,25 +622,7 @@

-

- - - - -
-
-
-
-57
-58
-59
-
-
# File 'lib/doing/note.rb', line 57
-
-def strip_lines
-  Note.new(map(&:strip))
-end
-
+
@@ -762,25 +634,7 @@

-

- - - - -
-
-
-
-61
-62
-63
-
-
# File 'lib/doing/note.rb', line 61
-
-def strip_lines!
-  replace strip_lines
-end
-
+
@@ -842,25 +696,7 @@

-

- - - - -
-
-
-
-83
-84
-85
-
-
# File 'lib/doing/note.rb', line 83
-
-def to_line(separator: ' ')
-  compress.strip_lines.join(separator)
-end
-
+
@@ -903,25 +739,7 @@

-

- - - - -
-
-
-
-70
-71
-72
-
-
# File 'lib/doing/note.rb', line 70
-
-def to_s(prefix: "\t\t")
-  compress.strip_lines.map { |l| "#{prefix}#{l}" }.join("\n")
-end
-
+ @@ -929,7 +747,7 @@

diff --git a/docs/doc/Doing/Pager.html b/docs/doc/Doing/Pager.html index 02004c3d..d4e6afc3 100644 --- a/docs/doc/Doing/Pager.html +++ b/docs/doc/Doing/Pager.html @@ -225,97 +225,7 @@

- - - - - -
-
-
-
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-
-
# File 'lib/doing/pager.rb', line 26
-
-def page(text)
-  unless @paginate
-    puts text
-    return
-  end
-
-  pager = which_pager
-  Doing.logger.debug('Pager:', "Using #{pager}")
-
-  read_io, write_io = IO.pipe
-
-  input = $stdin
-
-  pid = Kernel.fork do
-    write_io.close
-    input.reopen(read_io)
-    read_io.close
-
-    # Wait until we have input before we start the pager
-    IO.select [input]
-
-    begin
-      exec(pager)
-    rescue SystemCallError => e
-      raise Errors::DoingStandardError, "Pager error, #{e}"
-    end
-  end
-
-  begin
-    read_io.close
-    write_io.write(text)
-    write_io.close
-  rescue SystemCallError # => e
-    # raise Errors::DoingStandardError, "Pager error, #{e}"
-  end
-
-  _, status = Process.waitpid2(pid)
-  status.success?
-end
-
+
@@ -337,25 +247,7 @@

-
- - - - -
-
-
-
-10
-11
-12
-
-
# File 'lib/doing/pager.rb', line 10
-
-def paginate
-  @paginate ||= false
-end
-
+

@@ -396,25 +288,7 @@

-

- - - - -
-
-
-
-17
-18
-19
-
-
# File 'lib/doing/pager.rb', line 17
-
-def paginate=(should_paginate)
-  @paginate = should_paginate
-end
-
+ @@ -422,7 +296,7 @@

diff --git a/docs/doc/Doing/Plugins.html b/docs/doc/Doing/Plugins.html index 0a44eeef..001a039f 100644 --- a/docs/doc/Doing/Plugins.html +++ b/docs/doc/Doing/Plugins.html @@ -496,27 +496,7 @@

- - - - - -
-
-
-
-182
-183
-184
-185
-
-
# File 'lib/doing/plugin_manager.rb', line 182
-
-def available_plugins(type: :export)
-  type = valid_type(type)
-  plugins[type].keys.sort
-end
-
+
@@ -592,51 +572,7 @@

-

- - - - -
-
-
-
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-
-
# File 'lib/doing/plugin_manager.rb', line 158
-
-def list_plugins(options = {})
-  separator = options[:column] ? "\n" : "\t"
-  type = options[:type].nil? || options[:type] =~ /all/i ? 'all' : valid_type(options[:type])
-
-  case type
-  when :import
-    puts plugin_names(type: :import, separator: separator)
-  when :export
-    puts plugin_names(type: :export, separator: separator)
-  else
-    print 'Import plugins: '
-    puts plugin_names(type: :import, separator: ', ')
-    print 'Export plugins: '
-    puts plugin_names(type: :export, separator: ', ')
-  end
-end
-
+
@@ -658,59 +594,7 @@

-
- - - - -
-
-
-
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-
-
# File 'lib/doing/plugin_manager.rb', line 28
-
-def load_plugins(add_dir = nil)
-  plugins_path(add_dir).each do |plugin_search_path|
-    Dir.glob(File.join(plugin_search_path, '**', '*.rb')).sort.each do |plugin|
-      require plugin
-    end
-  end
-
-  Gem.find_latest_files('doing-plugin-*', true).sort.each do |plugin|
-    load plugin
-  end
-
-  # Gem.path.each do |path|
-  #   $LOAD_PATH.unshift path
-  #   Dir.glob(File.join(path, 'gems', 'doing-plugin-*', 'lib', '*.rb')).sort.each do |plugin|
-  #     require plugin.sub(%r{#{path}/gems/(.*?)-[\d.]+$}, '\1')
-  #   end
-  # end
-
-  plugins
-end
-
+

@@ -787,27 +671,7 @@

-

- - - - -
-
-
-
-195
-196
-197
-198
-
-
# File 'lib/doing/plugin_manager.rb', line 195
-
-def plugin_names(type: :export, separator: '|')
-  type = valid_type(type)
-  available_plugins(type: type).join(separator)
-end
-
+
@@ -869,35 +733,7 @@

-

- - - - -
-
-
-
-209
-210
-211
-212
-213
-214
-215
-216
-
-
# File 'lib/doing/plugin_manager.rb', line 209
-
-def plugin_regex(type: :export)
-  type = valid_type(type)
-  pattern = []
-  plugins[type].each do |_, options|
-    pattern << options[:trigger].normalize_trigger
-  end
-  Regexp.new("^(?:#{pattern.sort.uniq.join('|')})$", true)
-end
-
+
@@ -958,47 +794,7 @@

-

- - - - -
-
-
-
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-
-
# File 'lib/doing/plugin_manager.rb', line 226
-
-def plugin_templates(type: :export)
-  type = valid_type(type)
-  templates = []
-  plugs = plugins[type].clone
-  plugs.delete_if { |_t, o| o[:templates].nil? }.each do |_, options|
-    options[:templates].each do |t|
-      out = t[:name]
-      out += " (#{t[:format]})" if t.key?(:format)
-      templates << out
-    end
-  end
-
-  templates.sort.uniq
-end
-
+
@@ -1039,31 +835,7 @@

-

- - - - -
-
-
-
-18
-19
-20
-21
-22
-23
-
-
# File 'lib/doing/plugin_manager.rb', line 18
-
-def plugins
-  @plugins ||= {
-    import: {},
-    export: {}
-  }
-end
-
+
@@ -1124,29 +896,7 @@

-

- - - - -
-
-
-
-56
-57
-58
-59
-60
-
-
# File 'lib/doing/plugin_manager.rb', line 56
-
-def plugins_path(add_dir = nil)
-  paths = Array(File.join(File.dirname(__FILE__), 'plugins'))
-  paths << File.join(add_dir) if add_dir
-  paths.map { |d| File.expand_path(d) }
-end
-
+
@@ -1237,73 +987,7 @@

-

- - - - -
-
-
-
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-100
-
-
# File 'lib/doing/plugin_manager.rb', line 74
-
-def register(title, type, klass)
-  type = validate_plugin(title, type, klass)
-  return unless type
-
-  if title.is_a?(Array)
-    title.each { |t| register(t, type, klass) }
-    return
-  end
-
-  settings = if klass.respond_to? :settings
-               klass.settings
-             else
-               { trigger: title.normalize_trigger, config: {} }
-             end
-
-  plugins[type] ||= {}
-  plugins[type][title] = {
-    trigger: settings[:trigger].normalize_trigger || title.normalize_trigger,
-    class: klass,
-    templates: settings[:templates] || nil,
-    config: settings[:config] || {}
-  }
-
-  return unless ENV['DOING_PLUGIN_DEBUG']
-
-  Doing.logger.debug('Plugin Manager:', "Registered #{type} plugin \"#{title}\"")
-end
-
+
@@ -1413,49 +1097,7 @@

-

- - - - -
-
-
-
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-
-
# File 'lib/doing/plugin_manager.rb', line 276
-
-def template_for_trigger(trigger, type: :export, save_to: nil)
-  plugins[valid_type(type)].clone.delete_if { |_t, o| o[:templates].nil? }.each do |_, options|
-    options[:templates].each do |t|
-      next unless trigger =~ /^(?:#{t[:trigger].normalize_trigger})$/
-
-      tpl = options[:class].template(trigger)
-      return tpl unless save_to
-
-      raise PluginException.new('No default filename defined', :export, t[:name]) unless t.key?(:filename)
-
-      return save_template(tpl, save_to, t[:filename])
-    end
-  end
-  raise Errors::InvalidArgument, "No template type matched \"#{trigger}\""
-end
-
+
@@ -1517,41 +1159,7 @@

-

- - - - -
-
-
-
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-
-
# File 'lib/doing/plugin_manager.rb', line 250
-
-def template_regex(type: :export)
-  type = valid_type(type)
-  pattern = []
-  plugs = plugins[type].clone
-  plugs.delete_if { |_, o| o[:templates].nil? }.each do |_, options|
-    options[:templates].each do |t|
-      pattern << t[:trigger].normalize_trigger
-    end
-  end
-  Regexp.new("^(?:#{pattern.join('|')})$", true)
-end
-
+
@@ -1573,25 +1181,7 @@

-
- - - - -
-
-
-
-8
-9
-10
-
-
# File 'lib/doing/plugin_manager.rb', line 8
-
-def user_home
-  @user_home ||= Util.user_home
-end
-
+

@@ -1667,49 +1257,7 @@

-

- - - - -
-
-
-
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-
-
# File 'lib/doing/plugin_manager.rb', line 135
-
-def valid_type(type, default: nil)
-  type ||= default
-
-  t = type.to_s
-  type = case t
-         when /^i(m(p(o(r(t)?)?)?)?)?$/
-           :import
-         when /^e(x(p(o(r(t)?)?)?)?)?$/
-           :export
-         else
-           raise Errors::InvalidPluginType.new('Invalid plugin type', 'unrecognized')
-         end
-
-  type.to_sym
-end
-
+
@@ -1784,43 +1332,7 @@

-

- - - - -
-
-
-
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-
-
# File 'lib/doing/plugin_manager.rb', line 113
-
-def validate_plugin(title, type, klass)
-  type = valid_type(type)
-  if type == :import && !klass.respond_to?(:import)
-    raise Errors::PluginUncallable.new('Import plugins must respond to :import', type, title)
-  end
-
-  if type == :export && !klass.respond_to?(:render)
-    raise Errors::PluginUncallable.new('Export plugins must respond to :render', type, title)
-  end
-
-  type
-end
-
+ @@ -1828,7 +1340,7 @@

diff --git a/docs/doc/Doing/Prompt.html b/docs/doc/Doing/Prompt.html index 4fbd73fe..895fdc06 100644 --- a/docs/doc/Doing/Prompt.html +++ b/docs/doc/Doing/Prompt.html @@ -276,25 +276,7 @@

- - - - - -
-
-
-
-36
-37
-38
-
-
# File 'lib/doing/prompt/prompt.rb', line 36
-
-def default_answer
-  @default_answer ||= false
-end
-
+ @@ -335,25 +317,7 @@

- - - - - -
-
-
-
-27
-28
-29
-
-
# File 'lib/doing/prompt/prompt.rb', line 27
-
-def force_answer
-  @force_answer ||= nil
-end
-
+ @@ -362,7 +326,7 @@

diff --git a/docs/doc/Doing/PromptChoose.html b/docs/doc/Doing/PromptChoose.html index 4bd29e5e..627e3f43 100644 --- a/docs/doc/Doing/PromptChoose.html +++ b/docs/doc/Doing/PromptChoose.html @@ -291,57 +291,7 @@

- - - - - -
-
-
-
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-
-
# File 'lib/doing/prompt/choose.rb', line 17
-
-def choose_from(options, prompt: 'Make a selection: ', multiple: false, sorted: true, fzf_args: [])
-  return nil unless $stdout.isatty
-
-  # fzf_args << '-1' # User is expecting a menu, and even if only one it serves as confirmation
-  default_args = []
-  default_args << %(--prompt="#{prompt}")
-  default_args << "--height=#{options.count + 2}"
-  default_args << '--info=inline'
-  default_args << '--multi' if multiple
-  header = "esc: cancel,#{multiple ? ' tab: multi-select, ctrl-a: select all,' : ''} return: confirm"
-  default_args << %(--header="#{header}")
-  default_args.concat(fzf_args)
-  options.sort! if sorted
-
-  res = `echo #{Shellwords.escape(options.join("\n"))}|#{fzf} #{default_args.join(' ')}`
-  return false if res.strip.size.zero?
-
-  res
-end
-
+
@@ -516,147 +466,7 @@

-

- - - - -
-
-
-
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-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
-
-
# File 'lib/doing/prompt/choose.rb', line 53
-
-def choose_from_items(items, **opt)
-  return items unless $stdout.isatty
-
-  return nil unless items.count.positive?
-
-  case_sensitive = opt.fetch(:case, :smart).normalize_case
-  header = opt.fetch(:header, 'Arrows: navigate, tab: mark for selection, ctrl-a: select all, enter: commit')
-  prompt = opt.fetch(:prompt, 'Select entries to act on > ')
-  query = opt.fetch(:query) { opt.fetch(:search, '') }
-  include_section = opt.fetch(:include_section, false)
-
-  pad = items.length.to_s.length
-  options = items.map.with_index do |item, i|
-    out = [
-      format("%#{pad}d", i),
-      ') ',
-      format('%16s', item.date.strftime('%Y-%m-%d %H:%M')),
-      ' | ',
-      item.title
-    ]
-    if include_section
-      out.concat([
-        ' (',
-        item.section,
-        ') '
-      ])
-    end
-    out.join('')
-  end
-
-  fzf_args = [
-    %(--header="#{header}"),
-    %(--prompt="#{prompt.sub(/ *$/, ' ')}"),
-    opt.fetch(:multiple) ? '--multi' : '--no-multi',
-    '-0',
-    '--bind ctrl-a:select-all',
-    %(-q "#{query}"),
-    '--info=inline'
-  ]
-  fzf_args.push('-1') unless opt.fetch(:show_if_single, false)
-  fzf_args << case case_sensitive
-              when :sensitive
-                '+i'
-              when :ignore
-                '-i'
-              end
-  fzf_args << '-e' if opt.fetch(:exact, false)
-
-
-  unless opt.fetch(:menu)
-    raise InvalidArgument, "Can't skip menu when no query is provided" unless query && !query.empty?
-
-    fzf_args.concat([%(--filter="#{query}"), opt.fetch(:sort) ? '' : '--no-sort'])
-  end
-  res = `echo #{Shellwords.escape(options.join("\n"))}|#{fzf} #{fzf_args.join(' ')}`
-
-  selected = []
-  res.split(/\n/).each do |item|
-    idx = item.match(/^ *(\d+)\)/)[1].to_i
-    selected.push(items[idx])
-  end
-
-  opt.fetch(:multiple) ? selected : selected[0]
-end
-
+ @@ -664,7 +474,7 @@

diff --git a/docs/doc/Doing/PromptFZF.html b/docs/doc/Doing/PromptFZF.html index e81c9bdd..d59c4e9f 100644 --- a/docs/doc/Doing/PromptFZF.html +++ b/docs/doc/Doing/PromptFZF.html @@ -250,25 +250,7 @@

- - - - - -
-
-
-
-11
-12
-13
-
-
# File 'lib/doing/prompt/fzf.rb', line 11
-
-def fzf
-  @fzf ||= install_fzf
-end
-
+
@@ -330,91 +312,7 @@

-

- - - - -
-
-
-
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-
-
# File 'lib/doing/prompt/fzf.rb', line 47
-
-def install_fzf(force: false)
-  if force
-    uninstall_fzf
-  elsif which_fzf
-    return which_fzf
-  end
-
-  fzf_dir = File.join(File.dirname(__FILE__), '../../helpers/fzf')
-  FileUtils.mkdir_p(fzf_dir) unless File.directory?(fzf_dir)
-  fzf_bin = File.join(fzf_dir, 'bin/fzf')
-  return fzf_bin if File.exist?(fzf_bin)
-
-  prev_level = Doing.logger.level
-  Doing.logger.adjust_verbosity({ log_level: :info })
-  Doing.logger.log_now(:warn, 'fzf:', 'Compiling and installing fzf -- this will only happen once')
-  Doing.logger.log_now(:warn, 'fzf:', 'fzf is copyright Junegunn Choi, MIT License <https://github.com/junegunn/fzf/blob/master/LICENSE>')
-
-  silence_std
-  `'#{fzf_dir}/install' --bin --no-key-bindings --no-completion --no-update-rc --no-bash --no-zsh --no-fish &> /dev/null`
-  unless File.exist?(fzf_bin)
-    restore_std
-    Doing.logger.log_now(:warn, 'Error installing, trying again as root')
-    silence_std
-    `sudo '#{fzf_dir}/install' --bin --no-key-bindings --no-completion --no-update-rc --no-bash --no-zsh --no-fish &> /dev/null`
-  end
-  restore_std
-  unless File.exist?(fzf_bin)
-    Doing.logger.error('fzf:', 'unable to install fzf. You can install manually and Doing will use the system version.')
-    Doing.logger.error('fzf:', 'see https://github.com/junegunn/fzf#installation')
-    raise RuntimeError.new('Error installing fzf, please report at https://github.com/ttscoff/doing/issues')
-  end
-
-  Doing.logger.info('fzf:', "installed to #{fzf}")
-  Doing.logger.adjust_verbosity({ log_level: prev_level })
-  fzf_bin
-end
-
+
@@ -436,29 +334,7 @@

-
- - - - -
-
-
-
-18
-19
-20
-21
-22
-
-
# File 'lib/doing/prompt/fzf.rb', line 18
-
-def uninstall_fzf
-  fzf_bin = File.join(File.dirname(__FILE__), '../../helpers/fzf/bin/fzf')
-  FileUtils.rm_f(fzf_bin) if File.exist?(fzf_bin)
-  Doing.logger.warn('fzf:', "removed #{fzf_bin}")
-end
-
+

@@ -497,35 +373,7 @@

-

- - - - -
-
-
-
-29
-30
-31
-32
-33
-34
-35
-36
-
-
# File 'lib/doing/prompt/fzf.rb', line 29
-
-def which_fzf
-  fzf_dir = File.join(File.dirname(__FILE__), '../../helpers/fzf')
-  fzf_bin = File.join(fzf_dir, 'bin/fzf')
-  return fzf_bin if File.exist?(fzf_bin)
-
-  Doing.logger.debug('fzf:', 'Using user-installed fzf')
-  TTY::Which.which('fzf')
-end
-
+ @@ -533,7 +381,7 @@

diff --git a/docs/doc/Doing/PromptInput.html b/docs/doc/Doing/PromptInput.html index df8b560d..a1935c6c 100644 --- a/docs/doc/Doing/PromptInput.html +++ b/docs/doc/Doing/PromptInput.html @@ -291,33 +291,7 @@

- - - - - -
-
-
-
-19
-20
-21
-22
-23
-24
-25
-
-
# File 'lib/doing/prompt/input.rb', line 19
-
-def enter_text(prompt, default_response: '')
-  $stdin.reopen('/dev/tty')
-  return default_response if @default_answer
-
-  print "#{yellow(prompt).sub(/:?$/, ':')} #{reset}"
-  $stdin.gets.strip
-end
-
+
@@ -416,53 +390,7 @@

-

- - - - -
-
-
-
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-
-
# File 'lib/doing/prompt/input.rb', line 41
-
-def read_line(prompt: 'Enter text', completions: [], default_response: '')
-  $stdin.reopen('/dev/tty')
-  return default_response if @default_answer
-
-  unless completions.empty?
-    completions.sort!
-    comp = proc { |s| completions.grep(/^#{Regexp.escape(s)}/) }
-    Readline.completion_append_character = ' '
-    Readline.completion_proc = comp
-  end
-
-  begin
-    Readline.readline("#{yellow(prompt).sub(/:?$/, ':')} #{reset}", true).strip
-  rescue Interrupt
-    raise UserCancelled
-  end
-end
-
+
@@ -561,77 +489,7 @@

-

- - - - -
-
-
-
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-100
-101
-
-
# File 'lib/doing/prompt/input.rb', line 73
-
-def read_lines(prompt: 'Enter text', completions: [], default_response: '')
-  $stdin.reopen('/dev/tty')
-  return default_response if @default_answer
-
-  completions.sort!
-  comp = proc { |s| completions.grep(/^#{Regexp.escape(s)}/) }
-  Readline.completion_append_character = ' '
-  Readline.completion_proc = comp
-  puts format(['%<promptcolor>s%<prompt>s %<textcolor>sEnter a blank line',
-    '(%<keycolor>sreturn twice%<textcolor>s)',
-    'to end editing and save,',
-    '%<keycolor>sCTRL-C%<textcolor>s to cancel%<reset>s'].join(' '),
-    { promptcolor: boldgreen, prompt: prompt.sub(/:?$/, ':'),
-      textcolor: yellow, keycolor: boldwhite, reset: reset })
-
-  res = []
-
-  begin
-    while (line = Readline.readline('> ', true))
-      break if line.strip.empty?
-
-      res << line.chomp
-    end
-  rescue Interrupt
-    return nil
-  end
-
-  res.join("\n").strip
-end
-
+
@@ -696,49 +554,7 @@

-

- - - - -
-
-
-
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-
-
# File 'lib/doing/prompt/input.rb', line 113
-
-def request_lines(prompt: 'Enter text', default_response: '')
-  $stdin.reopen('/dev/tty')
-  return default_response if @default_answer
-
-  ask_note = []
-  reader = TTY::Reader.new(interrupt: -> { raise Errors::UserCancelled }, track_history: false)
-  puts "#{boldgreen(prompt.sub(/:?$/, ':'))} #{yellow('Hit return for a new line, ')}#{boldwhite('enter a blank line (')}#{boldyellow('return twice')}#{boldwhite(') to end editing')}"
-  loop do
-    res = reader.read_line(green('> '))
-    break if res.strip.empty?
-
-    ask_note.push(res)
-  end
-  ask_note.join("\n").strip
-end
-
+ @@ -746,7 +562,7 @@

diff --git a/docs/doc/Doing/PromptSTD.html b/docs/doc/Doing/PromptSTD.html index cfe3dd71..34132ba4 100644 --- a/docs/doc/Doing/PromptSTD.html +++ b/docs/doc/Doing/PromptSTD.html @@ -210,27 +210,7 @@

-
- - - - -
-
-
-
-9
-10
-11
-12
-
-
# File 'lib/doing/prompt/std.rb', line 9
-
-def clear_screen(msg = nil)
-  puts "\e[H\e[2J" if $stdout.tty?
-  puts msg if msg.good?
-end
-
+
@@ -252,27 +232,7 @@

-
- - - - -
-
-
-
-27
-28
-29
-30
-
-
# File 'lib/doing/prompt/std.rb', line 27
-
-def restore_std
-  $stdout = STDOUT
-  $stderr = STDERR
-end
-
+

@@ -315,27 +275,7 @@

-

- - - - -
-
-
-
-19
-20
-21
-22
-
-
# File 'lib/doing/prompt/std.rb', line 19
-
-def silence_std(file = '/dev/null')
-  $stdout = File.new(file, 'w')
-  $stderr = File.new(file, 'w')
-end
-
+ @@ -343,7 +283,7 @@

diff --git a/docs/doc/Doing/PromptYN.html b/docs/doc/Doing/PromptYN.html index 158d0b9b..380c5bfb 100644 --- a/docs/doc/Doing/PromptYN.html +++ b/docs/doc/Doing/PromptYN.html @@ -219,113 +219,7 @@

- - - - - -
-
-
-
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-
-
# File 'lib/doing/prompt/yn.rb', line 16
-
-def yn(question, default_response: false)
-  return @force_answer == :yes ? true : false unless @force_answer.nil?
-
-  $stdin.reopen('/dev/tty')
-
-  default = if default_response.is_a?(String)
-              default_response =~ /y/i ? true : false
-            else
-              default_response
-            end
-
-  # if global --default is set, answer default
-  return default if @default_answer
-
-  # if this isn't an interactive shell, answer default
-  return default unless $stdout.isatty
-
-  # clear the buffer
-  if ARGV&.length
-    ARGV.length.times do
-      ARGV.shift
-    end
-  end
-  system 'stty cbreak'
-
-  cw = white
-  cbw = boldwhite
-  cbg = boldgreen
-  cd = Color.default
-
-  options = unless default.nil?
-              "#{cw}[#{default ? "#{cbg}Y#{cw}/#{cbw}n" : "#{cbw}y#{cw}/#{cbg}N"}#{cw}]#{cd}"
-            else
-              "#{cw}[#{cbw}y#{cw}/#{cbw}n#{cw}]#{cd}"
-            end
-  $stdout.syswrite "#{cbw}#{question.sub(/\?$/, '')} #{options}#{cbw}?#{cd} "
-  res = $stdin.sysread 1
-  puts
-  system 'stty cooked'
-
-  res.chomp!
-  res.downcase!
-
-  return default if res.empty?
-
-  res =~ /y/i ? true : false
-end
-
+ @@ -333,7 +227,7 @@

diff --git a/docs/doc/Doing/Section.html b/docs/doc/Doing/Section.html index fe6b7c63..30277018 100644 --- a/docs/doc/Doing/Section.html +++ b/docs/doc/Doing/Section.html @@ -276,41 +276,7 @@

-
- - - - -
-
-
-
-8
-9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-
-
# File 'lib/doing/section.rb', line 8
-
-def initialize(title, original: nil)
-  super()
-
-  @title = title
-
-  @original = if original.nil?
-                "#{title}:"
-              else
-                original =~ /:(\s+@[^ (]+(\([^)]*\))?)*?$/ ? original : "#{original}:"
-              end
-end
-
+ @@ -339,25 +305,7 @@

-
- - - - -
-
-
-
-6
-7
-8
-
-
# File 'lib/doing/section.rb', line 6
-
-def original
-  @original
-end
-
+ @@ -381,25 +329,7 @@

-
- - - - -
-
-
-
-6
-7
-8
-
-
# File 'lib/doing/section.rb', line 6
-
-def title
-  @title
-end
-
+ @@ -440,25 +370,7 @@

- - - - - -
-
-
-
-20
-21
-22
-
-
# File 'lib/doing/section.rb', line 20
-
-def equal?(other)
-  @title == other.title
-end
-
+
@@ -480,25 +392,7 @@

-
- - - - -
-
-
-
-25
-26
-27
-
-
# File 'lib/doing/section.rb', line 25
-
-def to_s
-  @title
-end
-
+

@@ -506,7 +400,7 @@

diff --git a/docs/doc/Doing/StringHighlight.html b/docs/doc/Doing/StringHighlight.html index 48e62541..aef9b86a 100644 --- a/docs/doc/Doing/StringHighlight.html +++ b/docs/doc/Doing/StringHighlight.html @@ -288,79 +288,7 @@

-

- - - - -
-
-
-
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-
-
# File 'lib/doing/string/highlight.rb', line 31
-
-def highlight_search(search, distance: nil, negate: false, case_type: nil)
-  out = dup
-  matching = Doing.setting('search.matching', 'pattern').normalize_matching
-  distance ||= Doing.setting('search.distance', 3).to_i
-  case_type ||= Doing.setting('search.case', 'smart').normalize_case
-
-  if search.rx? || matching == :fuzzy
-    rx = search.to_rx(distance: distance, case_type: case_type)
-    out.gsub!(rx) { |m| m.bgyellow.black }
-  else
-    query = search.strip.to_phrase_query
-
-    if query[:must].nil? && query[:must_not].nil?
-      query[:must] = query[:should]
-      query[:should] = []
-    end
-    qs = []
-    qs.concat(query[:must]) if query[:must]
-    qs.concat(query[:should]) if query[:should]
-    qs.each do |s|
-      rx = Regexp.new(s.wildcard_to_rx, ignore_case(s, case_type))
-      out.gsub!(rx) do
-        m = Regexp.last_match
-        last = m.pre_match.last_color_code
-        "#{m[0].bgyellow.black}#{last}"
-      end
-    end
-  end
-  out
-end
-
+
@@ -372,25 +300,7 @@

-

- - - - -
-
-
-
-27
-28
-29
-
-
# File 'lib/doing/string/highlight.rb', line 27
-
-def highlight_search!(search, distance: nil, negate: false, case_type: nil)
-  replace highlight_search(search, distance: distance, negate: negate, case_type: case_type)
-end
-
+
@@ -450,35 +360,7 @@

-

- - - - -
-
-
-
-18
-19
-20
-21
-22
-23
-24
-25
-
-
# File 'lib/doing/string/highlight.rb', line 18
-
-def highlight_tags(color = 'yellow', last_color: nil)
-  unless last_color
-    color = color.split(' ') unless color.is_a?(Array)
-    tag_color = color.each_with_object([]) { |c, arr| arr << Doing::Color.send(c) }.join('')
-    last_color = last_color_code
-  end
-  gsub(/(\s|m)(@[^ ("']+)/, "\\1#{tag_color}\\2#{last_color}")
-end
-
+
@@ -520,25 +402,7 @@

-

- - - - -
-
-
-
-7
-8
-9
-
-
# File 'lib/doing/string/highlight.rb', line 7
-
-def highlight_tags!(color = 'yellow', last_color: nil)
-  replace highlight_tags(color)
-end
-
+
@@ -584,25 +448,7 @@

-

- - - - -
-
-
-
-73
-74
-75
-
-
# File 'lib/doing/string/highlight.rb', line 73
-
-def last_color
-  scan(/\e\[[\d;]+m/).join('')
-end
-
+
@@ -641,25 +487,7 @@

-

- - - - -
-
-
-
-82
-83
-84
-
-
# File 'lib/doing/string/highlight.rb', line 82
-
-def uncolor
-  gsub(/\e\[[\d;]+m/, '')
-end
-
+
@@ -687,25 +515,7 @@

-

- - - - -
-
-
-
-89
-90
-91
-
-
# File 'lib/doing/string/highlight.rb', line 89
-
-def uncolor!
-  replace uncolor
-end
-
+ @@ -713,7 +523,7 @@

diff --git a/docs/doc/Doing/StringNormalize.html b/docs/doc/Doing/StringNormalize.html index f441a006..6fa01b26 100644 --- a/docs/doc/Doing/StringNormalize.html +++ b/docs/doc/Doing/StringNormalize.html @@ -518,39 +518,7 @@

- - - - - -
-
-
-
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-
-
# File 'lib/doing/normalize.rb', line 54
-
-def normalize_age(default = :newest)
-  case self
-  when /^o/i
-    :oldest
-  when /^n/i
-    :newest
-  else
-    default.is_a?(Symbol) ? default : default.normalize_age
-  end
-end
-
+
@@ -578,25 +546,7 @@

-

- - - - -
-
-
-
-66
-67
-68
-
-
# File 'lib/doing/normalize.rb', line 66
-
-def normalize_age!(default = :newest)
-  replace normalize_age(default)
-end
-
+
@@ -635,47 +585,7 @@

-

- - - - -
-
-
-
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-
-
# File 'lib/doing/normalize.rb', line 118
-
-def normalize_bool(default = :and)
-  case self
-  when /(and|all)/i
-    :and
-  when /(any|or)/i
-    :or
-  when /(not|none)/i
-    :not
-  when /^p/i
-    :pattern
-  else
-    default.is_a?(Symbol) ? default : default.normalize_bool
-  end
-end
-
+
@@ -703,25 +613,7 @@

-

- - - - -
-
-
-
-134
-135
-136
-
-
# File 'lib/doing/normalize.rb', line 134
-
-def normalize_bool!(default = :and)
-  replace normalize_bool(default)
-end
-
+
@@ -760,43 +652,7 @@

-

- - - - -
-
-
-
-95
-96
-97
-98
-99
-100
-101
-102
-103
-104
-105
-106
-
-
# File 'lib/doing/normalize.rb', line 95
-
-def normalize_case(default = :smart)
-  case self
-  when /^(c|sens)/i
-    :sensitive
-  when /^i/i
-    :ignore
-  when /^s/i
-    :smart
-  else
-    default.is_a?(Symbol) ? default : default.normalize_case
-  end
-end
-
+
@@ -824,25 +680,7 @@

-

- - - - -
-
-
-
-109
-110
-111
-
-
# File 'lib/doing/normalize.rb', line 109
-
-def normalize_case!(default = :smart)
-  replace normalize_case(default)
-end
-
+
@@ -854,43 +692,7 @@

-

- - - - -
-
-
-
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-
-
# File 'lib/doing/normalize.rb', line 179
-
-def normalize_change_type
-  case self
-  when /^c/i
-    :changed
-  when /^i/i
-    :improved
-  when /^f/i
-    :fixed
-  when /^n/i
-    :new
-  end
-end
-
+

@@ -950,43 +752,7 @@

-

- - - - -
-
-
-
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-
-
# File 'lib/doing/normalize.rb', line 36
-
-def normalize_list_style(default = :space)
-  case self
-  when /^c(om|sv)/i
-    :comma
-  when /^c/i
-    :column
-  when /^t/i
-    :tab
-  else
-    default.is_a?(Symbol) ? default : default.normalize_list_style
-  end
-end
-
+
@@ -1048,43 +814,7 @@

-

- - - - -
-
-
-
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-
-
# File 'lib/doing/normalize.rb', line 146
-
-def normalize_matching(default = :pattern)
-  case self
-  when /^f/i
-    :fuzzy
-  when /^p/i
-    :pattern
-  when /^e/i
-    :exact
-  else
-    default.is_a?(Symbol) ? default : default.normalize_matching
-  end
-end
-
+
@@ -1112,25 +842,7 @@

-

- - - - -
-
-
-
-160
-161
-162
-
-
# File 'lib/doing/normalize.rb', line 160
-
-def normalize_matching!(default = :pattern)
-  replace normalize_bool(default)
-end
-
+
@@ -1142,39 +854,7 @@

-

- - - - -
-
-
-
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-
-
# File 'lib/doing/normalize.rb', line 79
-
-def normalize_order(default = :asc)
-  case self
-  when /^a/i
-    :asc
-  when /^d/i
-    :desc
-  else
-    default.is_a?(Symbol) ? default : default.normalize_order
-  end
-end
-
+
@@ -1213,25 +893,7 @@

-

- - - - -
-
-
-
-75
-76
-77
-
-
# File 'lib/doing/normalize.rb', line 75
-
-def normalize_order!(default = :asc)
-  replace normalize_order(default)
-end
-
+
@@ -1270,39 +932,7 @@

-

- - - - -
-
-
-
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-
-
# File 'lib/doing/normalize.rb', line 13
-
-def normalize_tag_sort(default = :name)
-  case self
-  when /^n/i
-    :name
-  when /^t/i
-    :time
-  else
-    default.is_a?(Symbol) ? default : default.normalize_tag_sort
-  end
-end
-
+
@@ -1330,25 +960,7 @@

-

- - - - -
-
-
-
-25
-26
-27
-
-
# File 'lib/doing/normalize.rb', line 25
-
-def normalize_tag_sort!(default = :name)
-  replace normalize_tag_sort(default)
-end
-
+
@@ -1388,25 +1000,7 @@

-

- - - - -
-
-
-
-170
-171
-172
-
-
# File 'lib/doing/normalize.rb', line 170
-
-def normalize_trigger
-  gsub(/\((?!\?:)/, '(?:').downcase
-end
-
+
@@ -1434,25 +1028,7 @@

-

- - - - -
-
-
-
-175
-176
-177
-
-
# File 'lib/doing/normalize.rb', line 175
-
-def normalize_trigger!
-  replace normalize_trigger
-end
-
+ @@ -1460,7 +1036,7 @@

diff --git a/docs/doc/Doing/StringQuery.html b/docs/doc/Doing/StringQuery.html index 74c42e01..b20983b2 100644 --- a/docs/doc/Doing/StringQuery.html +++ b/docs/doc/Doing/StringQuery.html @@ -365,27 +365,7 @@

- - - - - -
-
-
-
-24
-25
-26
-27
-
-
# File 'lib/doing/string/query.rb', line 24
-
-def ignore?
-  line = self
-  line =~ /^#/ || line =~ /^\s*$/
-end
-
+
@@ -459,25 +439,7 @@

-

- - - - -
-
-
-
-15
-16
-17
-
-
# File 'lib/doing/string/query.rb', line 15
-
-def ignore_case(search, case_type)
-  (case_type == :smart && search !~ /[A-Z]/) || case_type == :ignore
-end
-
+
@@ -516,25 +478,7 @@

-

- - - - -
-
-
-
-34
-35
-36
-
-
# File 'lib/doing/string/query.rb', line 34
-
-def rx?
-  self =~ %r{(^/.*?/$|^')}
-end
-
+
@@ -573,35 +517,7 @@

-

- - - - -
-
-
-
-130
-131
-132
-133
-134
-135
-136
-137
-
-
# File 'lib/doing/string/query.rb', line 130
-
-def to_bool
-  case self
-  when /^[yt1]/i
-    true
-  else
-    false
-  end
-end
-
+
@@ -640,31 +556,7 @@

-

- - - - -
-
-
-
-93
-94
-95
-96
-97
-98
-
-
# File 'lib/doing/string/query.rb', line 93
-
-def to_phrase_query
-  parser = PhraseParser::QueryParser.new
-  transformer = PhraseParser::QueryTransformer.new
-  parse_tree = parser.parse(self)
-  transformer.apply(parse_tree).to_elasticsearch
-end
-
+
@@ -703,31 +595,7 @@

-

- - - - -
-
-
-
-105
-106
-107
-108
-109
-110
-
-
# File 'lib/doing/string/query.rb', line 105
-
-def to_query
-  parser = BooleanTermParser::QueryParser.new
-  transformer = BooleanTermParser::QueryTransformer.new
-  parse_tree = parser.parse(self)
-  transformer.apply(parse_tree).to_elasticsearch
-end
-
+
@@ -816,67 +684,7 @@

Examples:

-
- - - - -
-
-
-
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-
-
# File 'lib/doing/string/query.rb', line 63
-
-def to_rx(distance: nil, case_type: nil)
-  distance ||= Doing.config.fetch('search', 'distance', 3).to_i
-  case_type ||= Doing.config.fetch('search', 'case', 'smart')&.normalize_case
-  case_sensitive = case case_type
-                   when :smart
-                     self =~ /[A-Z]/ ? true : false
-                   when :sensitive
-                     true
-                   else
-                     false
-                   end
-
-  pattern = case dup.strip
-            when %r{^/.*?/$}
-              sub(%r{/(.*?)/}, '\1')
-            when /^'/
-              sub(/^'(.*?)'?$/, '\1')
-            else
-              split(/ +/).map do |w|
-                w.split('').join(".{0,#{distance}}").gsub(/\+/, '\+').wildcard_to_rx
-              end.join('.*?')
-            end
-  Regexp.new(pattern, !case_sensitive)
-end
-
+
@@ -915,33 +723,7 @@

-

- - - - -
-
-
-
-117
-118
-119
-120
-121
-122
-123
-
-
# File 'lib/doing/string/query.rb', line 117
-
-def truthy?
-  if self =~ /^(0|f(alse)?|n(o)?)$/i
-    false
-  else
-    true
-  end
-end
-
+
@@ -981,25 +763,7 @@

-

- - - - -
-
-
-
-44
-45
-46
-
-
# File 'lib/doing/string/query.rb', line 44
-
-def wildcard_to_rx
-  gsub(/\?/, '\S').gsub(/\*/, '\S*?').gsub(/\]\]/, '--')
-end
-
+ @@ -1007,7 +771,7 @@

diff --git a/docs/doc/Doing/StringTags.html b/docs/doc/Doing/StringTags.html index f115ed0e..12a5ae0b 100644 --- a/docs/doc/Doing/StringTags.html +++ b/docs/doc/Doing/StringTags.html @@ -386,25 +386,7 @@

- - - - - -
-
-
-
-11
-12
-13
-
-
# File 'lib/doing/string/tags.rb', line 11
-
-def add_at
-  strip.sub(/^([+-]*)@?/, '\1@')
-end
-
+
@@ -479,31 +461,7 @@

-

- - - - -
-
-
-
-59
-60
-61
-62
-63
-64
-
-
# File 'lib/doing/string/tags.rb', line 59
-
-def add_tags(tags, remove: false)
-  title = dup
-  tags = tags.to_tags
-  tags.each { |tag| title.tag!(tag, remove: remove) }
-  title
-end
-
+
@@ -531,25 +489,7 @@

-

- - - - -
-
-
-
-67
-68
-69
-
-
# File 'lib/doing/string/tags.rb', line 67
-
-def add_tags!(tags, remove: false)
-  replace add_tags(tags, remove: remove)
-end
-
+
@@ -588,51 +528,7 @@

-

- - - - -
-
-
-
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-
-
# File 'lib/doing/string/tags.rb', line 159
-
-def dedup_tags
-  title = dup
-  tags = title.scan(/(?<=\A| )(@(\S+?)(\([^)]+\))?)(?= |\Z)/).uniq
-  tags.each do |tag|
-    found = false
-    title.gsub!(/( |^)#{Regexp.escape(tag[1])}(\([^)]+\))?(?= |$)/) do |m|
-      if found
-        ''
-      else
-        found = true
-        m
-      end
-    end
-  end
-  title
-end
-
+
@@ -660,25 +556,7 @@

-

- - - - -
-
-
-
-177
-178
-179
-
-
# File 'lib/doing/string/tags.rb', line 177
-
-def dedup_tags!
-  replace dedup_tags
-end
-
+
@@ -717,25 +595,7 @@

-

- - - - -
-
-
-
-20
-21
-22
-
-
# File 'lib/doing/string/tags.rb', line 20
-
-def remove_at
-  strip.sub(/^([+-]*)@?/, '\1')
-end
-
+
@@ -776,25 +636,7 @@

-

- - - - -
-
-
-
-31
-32
-33
-
-
# File 'lib/doing/string/tags.rb', line 31
-
-def split_tags
-  gsub(/ *, */, ' ').scan(/(@?(?:\S+(?:\(.+\)))|@?(?:\S+))/).map(&:first).map(&:remove_at).sort.uniq
-end
-
+
@@ -954,139 +796,7 @@

-

- - - - -
-
-
-
-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
-150
-151
-152
-
-
# File 'lib/doing/string/tags.rb', line 93
-
-def tag(tag, value: nil, remove: false, rename_to: nil, regex: false, single: false, force: false)
-  log_level = single ? :info : :debug
-  title = dup
-  title.chomp!
-  tag = tag.sub(/^@?/, '')
-  case_sensitive = tag !~ /[A-Z]/
-
-  rx_tag = if regex
-             tag.gsub(/\./, '\S')
-           else
-             tag.gsub(/\?/, '.').gsub(/\*/, '\S*?')
-           end
-
-  if remove || rename_to
-    rx = Regexp.new("(?<=^| )@#{rx_tag}(?<parens>\\((?<value>[^)]*)\\))?(?= |$)", case_sensitive)
-    m = title.match(rx)
-
-    if m.nil? && rename_to && force
-      title.tag!(rename_to, value: value, single: single)
-    elsif m
-      title.gsub!(rx) do
-        rename_to ? "@#{rename_to}#{value.nil? ? m['parens'] : "(#{value})"}" : ''
-      end
-
-      title.dedup_tags!
-      title.chomp!
-
-      if rename_to
-        f = "@#{tag}".cyan
-        t = "@#{rename_to}".cyan
-        Doing.logger.write(log_level, 'Tag:', %(renamed #{f} to #{t} in "#{title}"))
-      else
-        f = "@#{tag}".cyan
-        Doing.logger.write(log_level, 'Tag:', %(removed #{f} from "#{title}"))
-      end
-    else
-      Doing.logger.debug('Skipped:', "not tagged #{"@#{tag}".cyan}")
-    end
-  elsif title =~ /@#{tag}(?=[ (]|$)/ && !value.good?
-    Doing.logger.debug('Skipped:', "already tagged #{"@#{tag}".cyan}")
-    return title
-  else
-    add = tag
-    add += "(#{value})" unless value.nil?
-
-    title.chomp!
-
-    if value && title =~ /@#{tag}(?=[ (]|$)/
-      title.sub!(/@#{tag}(\(.*?\))?/, "@#{add}")
-    else
-      title += " @#{add}"
-    end
-
-    title.dedup_tags!
-    title.chomp!
-    Doing.logger.write(log_level, 'Tag:', %(added #{('@' + tag).cyan} to "#{title}"))
-  end
-
-  title.gsub(/ +/, ' ')
-end
-
+
@@ -1115,25 +825,7 @@

-

- - - - -
-
-
-
-76
-77
-78
-
-
# File 'lib/doing/string/tags.rb', line 76
-
-def tag!(tag, **options)
-  replace tag(tag, **options)
-end
-
+
@@ -1174,35 +866,7 @@

-

- - - - -
-
-
-
-42
-43
-44
-45
-46
-47
-48
-49
-
-
# File 'lib/doing/string/tags.rb', line 42
-
-def to_tags
-  arr = split_tags.map(&:add_at)
-  if block_given?
-    yield arr
-  else
-    arr
-  end
-end
-
+ @@ -1210,7 +874,7 @@

diff --git a/docs/doc/Doing/StringTransform.html b/docs/doc/Doing/StringTransform.html index 547d0b24..356ec89f 100644 --- a/docs/doc/Doing/StringTransform.html +++ b/docs/doc/Doing/StringTransform.html @@ -339,29 +339,7 @@

- - - - - -
-
-
-
-102
-103
-104
-105
-106
-
-
# File 'lib/doing/string/transform.rb', line 102
-
-def cap_first
-  sub(/^\w/) do |m|
-    m.upcase
-  end
-end
-
+
@@ -383,25 +361,7 @@

-
- - - - -
-
-
-
-9
-10
-11
-
-
# File 'lib/doing/string/transform.rb', line 9
-
-def compress
-  gsub(/ +/, ' ').strip
-end
-
+

@@ -413,25 +373,7 @@

-

- - - - -
-
-
-
-13
-14
-15
-
-
# File 'lib/doing/string/transform.rb', line 13
-
-def compress!
-  replace compress
-end
-
+

@@ -498,93 +440,7 @@

-

- - - - -
-
-
-
-130
-131
-132
-133
-134
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-
-
# File 'lib/doing/string/transform.rb', line 130
-
-def set_type(kind = nil)
-  if kind
-    case kind.to_s
-    when /^a/i
-      gsub(/^\[ *| *\]$/, '').split(/ *, */)
-    when /^i/i
-      to_i
-    when /^(fa|tr)/i
-      to_bool
-    when /^f/i
-      to_f
-    when /^sy/i
-      sub(/^:/, '').to_sym
-    when /^b/i
-      self =~ /^(true|yes)$/ ? true : false
-    else
-      to_s
-    end
-  else
-    case self
-    when /(^\[.*?\]$| *, *)/
-      gsub(/^\[ *| *\]$/, '').split(/ *, */)
-    when /^[0-9]+$/
-      to_i
-    when /^[0-9]+\.[0-9]+$/
-      to_f
-    when /^:\w+/
-      sub(/^:/, '').to_sym
-    when /^(true|yes)$/i
-      true
-    when /^(false|no)$/i
-      false
-    else
-      to_s
-    end
-  end
-end
-
+
@@ -596,63 +452,7 @@

-

- - - - -
-
-
-
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-
-
# File 'lib/doing/string/transform.rb', line 17
-
-def simple_wrap(width)
-  str = gsub(/@\S+\(.*?\)/) { |tag| tag.gsub(/\s/, '%%%%') }
-  words = str.split(/ /).map { |word| word.gsub(/%%%%/, ' ') }
-  out = []
-  line = []
-
-  words.each do |word|
-    if word.uncolor.length >= width
-      chars = word.uncolor.split('')
-      out << chars.slice!(0, width - 1).join('') while chars.count >= width
-      line << chars.join('')
-      next
-    elsif line.join(' ').uncolor.length + word.uncolor.length + 1 > width
-      out.push(line.join(' '))
-      line.clear
-    end
-
-    line << word.uncolor
-  end
-  out.push(line.join(' '))
-  out.join("\n")
-end
-
+
@@ -664,29 +464,7 @@

-

- - - - -
-
-
-
-168
-169
-170
-171
-172
-
-
# File 'lib/doing/string/transform.rb', line 168
-
-def titlecase
-  tr('_', ' ').
-  gsub(/\s+/, ' ').
-  gsub(/\b\w/){ $`[-1,1] == "'" ? $& : $&.upcase }
-end
-
+
@@ -728,25 +506,7 @@

-

- - - - -
-
-
-
-114
-115
-116
-
-
# File 'lib/doing/string/transform.rb', line 114
-
-def to_p(number)
-  number == 1 ? self : "#{self}s"
-end
-
+
@@ -821,117 +581,7 @@

-

- - - - -
-
-
-
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-
-
# File 'lib/doing/string/transform.rb', line 47
-
-def wrap(len, pad: 0, indent: '  ', offset: 0, prefix: '', color: '', after: '', reset: '', pad_first: false)
-  last_color = color.empty? ? '' : after.last_color
-  note_rx = /(?mi)(?<!\\)%(?<width>-?\d+)?(?:\^(?<mchar>.))?(?:(?<ichar>[ _t]|[^a-z0-9])(?<icount>\d+))?(?<prefix>.[ _t]?)?note/
-  note = ''
-  after = after.dup if after.frozen?
-  after.sub!(note_rx) do
-    note = Regexp.last_match(0)
-    ''
-  end
-
-  left_pad = ' ' * offset
-  left_pad += indent
-
-  # return "#{left_pad}#{prefix}#{color}#{self}#{last_color} #{note}" unless len.positive?
-
-  # Don't break inside of tag values
-  str = gsub(/@\S+\(.*?\)/) { |tag| tag.gsub(/\s/, '%%%%') }.gsub(/\n/, ' ')
-
-  words = str.split(/ /).map { |word| word.gsub(/%%%%/, ' ') }
-  out = []
-  line = []
-
-  words.each do |word|
-    if word.uncolor.length >= len
-      chars = word.uncolor.split('')
-      out << chars.slice!(0, len - 1).join('') while chars.count >= len
-      line << chars.join('')
-      next
-    elsif line.join(' ').uncolor.length + word.uncolor.length + 1 > len
-      out.push(line.join(' '))
-      line.clear
-    end
-
-    line << word.uncolor
-  end
-  out.push(line.join(' '))
-
-  last_color = ''
-  out[0] = format("%-#{pad}s%s%s", out[0], last_color, after)
-
-  out.map.with_index { |l, idx|
-    if !pad_first && idx == 0
-      "#{color}#{prefix}#{l}#{last_color}"
-    else
-      "#{left_pad}#{color}#{prefix}#{l}#{last_color}"
-    end
-  }.join("\n") + " #{note}".chomp
-  # res.join("\n").strip + last_color + " #{note}".chomp
-end
-
+ @@ -939,7 +589,7 @@

diff --git a/docs/doc/Doing/StringTruncate.html b/docs/doc/Doing/StringTruncate.html index b517e2d6..28bba39c 100644 --- a/docs/doc/Doing/StringTruncate.html +++ b/docs/doc/Doing/StringTruncate.html @@ -295,47 +295,7 @@

- - - - - -
-
-
-
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-
-
# File 'lib/doing/string/truncate.rb', line 13
-
-def trunc(len, ellipsis: '...')
-  return self if length <= len
-
-  total = 0
-  res = []
-
-  split(/ /).each do |word|
-    break if total + 1 + word.length > len
-
-    total += 1 + word.length
-    res.push(word)
-  end
-  res.join(' ') + ellipsis
-end
-
+
@@ -347,25 +307,7 @@

-

- - - - -
-
-
-
-28
-29
-30
-
-
# File 'lib/doing/string/truncate.rb', line 28
-
-def trunc!(len, ellipsis: '...')
-  replace trunc(len, ellipsis: ellipsis)
-end
-
+

@@ -406,47 +348,7 @@

-

- - - - -
-
-
-
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-
-
# File 'lib/doing/string/truncate.rb', line 37
-
-def truncend(len, ellipsis: '...')
-  return self if length <= len
-
-  total = 0
-  res = []
-
-  split(/ /).reverse.each do |word|
-    break if total + 1 + word.length > len
-
-    total += 1 + word.length
-    res.unshift(word)
-  end
-  ellipsis + res.join(' ')
-end
-
+
@@ -458,25 +360,7 @@

-

- - - - -
-
-
-
-52
-53
-54
-
-
# File 'lib/doing/string/truncate.rb', line 52
-
-def truncend!(len, ellipsis: '...')
-  replace truncend(len, ellipsis: ellipsis)
-end
-
+
@@ -534,35 +418,7 @@

-

- - - - -
-
-
-
-62
-63
-64
-65
-66
-67
-68
-69
-
-
# File 'lib/doing/string/truncate.rb', line 62
-
-def truncmiddle(len, ellipsis: '...')
-  return self if length <= len
-  len -= (ellipsis.length / 2).to_i
-  half = (len / 2).to_i
-  start = trunc(half, ellipsis: ellipsis)
-  finish = truncend(half, ellipsis: '')
-  start + finish
-end
-
+
@@ -574,25 +430,7 @@

-

- - - - -
-
-
-
-71
-72
-73
-
-
# File 'lib/doing/string/truncate.rb', line 71
-
-def truncmiddle!(len, ellipsis: '...')
-  replace truncmiddle(len, ellipsis: ellipsis)
-end
-
+
@@ -600,7 +438,7 @@

diff --git a/docs/doc/Doing/StringURL.html b/docs/doc/Doing/StringURL.html index 4b44bf4f..638baa41 100644 --- a/docs/doc/Doing/StringURL.html +++ b/docs/doc/Doing/StringURL.html @@ -255,39 +255,7 @@

-
- - - - -
-
-
-
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-
-
# File 'lib/doing/string/url.rb', line 71
-
-def clean_unlinked_urls
-  gsub(/<(\w+:.*?)>/) do |match|
-    m = Regexp.last_match
-    if m[1] =~ /<a href/
-      match
-    else
-      %(<a href="#{m[1]}" title="Link to #{m[1]}">[link]</a>)
-    end
-  end
-end
-
+
@@ -351,39 +319,7 @@
- - - - -
-
-
-
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-
-
# File 'lib/doing/string/url.rb', line 16
-
-def link_urls(**opt)
-  fmt = opt.fetch(:format, :html)
-  return self unless fmt
-
-  str = dup
-
-  str = str.remove_self_links if fmt == :markdown
-
-  str.replace_qualified_urls(format: fmt).clean_unlinked_urls
-end
-
+
@@ -411,27 +347,7 @@
- - - - -
-
-
-
-28
-29
-30
-31
-
-
# File 'lib/doing/string/url.rb', line 28
-
-def link_urls!(**opt)
-  fmt = opt.fetch(:format, :html)
-  replace link_urls(format: fmt)
-end
-
+
@@ -453,39 +369,7 @@
@@ -507,65 +391,7 @@

-
- - - - -
-
-
-
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-
-
# File 'lib/doing/string/url.rb', line 46
-
-def replace_qualified_urls(**options)
-  fmt = options.fetch(:format, :html)
-  gsub(%r{(?mi)(?x:
-  (?<!["'\[(\\])
-  (?<protocol>(?:http|https)://)
-  (?<domain>[\w\-]+(?:\.[\w\-]+)+)
-  (?<path>[\w\-.,@?^=%&;:/~+#]*[\w\-@^=%&;/~+#])?
-  )}) do |_match|
-    m = Regexp.last_match
-    url = "#{m['domain']}#{m['path']}"
-    proto = m['protocol'].nil? ? 'http://' : m['protocol']
-    case fmt
-    when :terminal
-      TTY::Link.link_to("#{proto}#{url}", "#{proto}#{url}")
-    when :html
-      %(<a href="#{proto}#{url}" title="Link to #{m['domain']}">[#{url}]</a>)
-    when :markdown
-      "[#{url}](#{proto}#{url})"
-    else
-      m[0]
-    end
-  end
-end
-
+

@@ -573,7 +399,7 @@

diff --git a/docs/doc/Doing/SymbolNormalize.html b/docs/doc/Doing/SymbolNormalize.html index 2353ee07..a93fb6e9 100644 --- a/docs/doc/Doing/SymbolNormalize.html +++ b/docs/doc/Doing/SymbolNormalize.html @@ -263,25 +263,7 @@

-

- - - - -
-
-
-
-205
-206
-207
-
-
# File 'lib/doing/normalize.rb', line 205
-
-def normalize_age(default = :newest)
-  to_s.normalize_age(default)
-end
-
+
@@ -293,25 +275,7 @@

-

- - - - -
-
-
-
-201
-202
-203
-
-
# File 'lib/doing/normalize.rb', line 201
-
-def normalize_bool(default = :and)
-  to_s.normalize_bool(default)
-end
-
+
@@ -323,25 +287,7 @@

-

- - - - -
-
-
-
-213
-214
-215
-
-
# File 'lib/doing/normalize.rb', line 213
-
-def normalize_case(default = :smart)
-  to_s.normalize_case(default)
-end
-
+
@@ -353,25 +299,7 @@

-

- - - - -
-
-
-
-217
-218
-219
-
-
# File 'lib/doing/normalize.rb', line 217
-
-def normalize_matching(default = :pattern)
-  to_s.normalize_matching(default)
-end
-
+
@@ -383,25 +311,7 @@

-

- - - - -
-
-
-
-209
-210
-211
-
-
# File 'lib/doing/normalize.rb', line 209
-
-def normalize_order(default = :asc)
-  to_s.normalize_order(default)
-end
-
+
@@ -413,25 +323,7 @@

-

- - - - -
-
-
-
-197
-198
-199
-
-
# File 'lib/doing/normalize.rb', line 197
-
-def normalize_tag_sort(default = :name)
-  to_s.normalize_tag_sort
-end
-
+
@@ -439,7 +331,7 @@

diff --git a/docs/doc/Doing/TaskPaperExport.html b/docs/doc/Doing/TaskPaperExport.html index 310657f1..31dd8183 100644 --- a/docs/doc/Doing/TaskPaperExport.html +++ b/docs/doc/Doing/TaskPaperExport.html @@ -192,47 +192,7 @@

-

- - - - -
-
-
-
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-
-
# File 'lib/doing/plugins/export/taskpaper_export.rb', line 17
-
-def self.render(wwid, items, variables: {})
-  return if items.nil?
-
-  options = variables[:options]
-
-  options[:highlight] = false
-  options[:wrap_width] = 0
-  options[:tags_color] = false
-  options[:output] = 'template'
-  options[:template] = '- %title @date(%date)%note'
-
-  Doing.logger.debug('TaskPaper Export:', "#{items.count} items output to TaskPaper format")
-  @out = wwid.list_section(options)
-end
-
+
@@ -244,29 +204,7 @@

-

- - - - -
-
-
-
-11
-12
-13
-14
-15
-
-
# File 'lib/doing/plugins/export/taskpaper_export.rb', line 11
-
-def self.settings
-  {
-    trigger: 'task(?:paper)?|tp'
-  }
-end
-
+
@@ -274,7 +212,7 @@

diff --git a/docs/doc/Doing/TemplateExport.html b/docs/doc/Doing/TemplateExport.html index 51339674..dd3c62c5 100644 --- a/docs/doc/Doing/TemplateExport.html +++ b/docs/doc/Doing/TemplateExport.html @@ -219,271 +219,7 @@

-

- - - - -
-
-
-
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-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
-
-
# File 'lib/doing/plugins/export/template_export.rb', line 19
-
-def self.render(wwid, items, variables: {})
-  Doing.logger.benchmark(:template_render, :start)
-  return if items.nil?
-
-  opt = variables[:options]
-
-  out = ''
-  items.each do |item|
-    if opt[:highlight] && item.title =~ /@#{Doing.setting('marker_tag')}\b/i
-      flag = Doing::Color.send(Doing.setting('marker_color'))
-      reset = Doing::Color.reset + Doing::Color.default
-    else
-      flag = ''
-      reset = ''
-    end
-
-    placeholders = {}
-
-    if !item.note.empty? && Doing.setting('include_notes')
-      note = item.note.map(&:strip).delete_if(&:empty?)
-      note.map! { |line| "#{line.sub(/^\t*/, '')}  " }
-
-      if opt[:wrap_width]&.positive?
-        width = opt[:wrap_width]
-        note.map! do |line|
-          line.simple_wrap(width)
-          # line.chomp.gsub(/(.{1,#{width}})(\s+|\Z)/, "\\1\n")
-        end
-        note.delete_if(&:empty?)
-      end
-    else
-      note = []
-    end
-
-    placeholders['id'] = item.id
-
-    placeholders['tags'] = item.tags
-
-    placeholders['date'] = item.date.strftime(opt[:format])
-
-    interval = wwid.get_interval(item, record: true, formatted: false) if opt[:times]
-    if interval
-      interval = case opt[:interval_format].to_sym
-                 when :human
-                   interval.time_string(format: :hm)
-                 when :text
-                   interval.time_string(format: :clock)
-                 else
-                   interval.time_string(format: opt[:interval_format].to_sym)
-                 end
-    end
-
-    interval ||= ''
-    placeholders['interval'] = interval
-
-    duration = item.duration if opt[:duration]
-    if duration
-      duration = case opt[:interval_format].to_sym
-                 when :human
-                   duration.time_string(format: :hm)
-                 when :text
-                   duration.time_string(format: :clock)
-                 else
-                   duration.time_string(format: opt[:interval_format].to_sym)
-                 end
-    end
-    duration ||= ''
-    placeholders['duration'] = duration
-
-    placeholders['shortdate'] = format('%13s', item.date.relative_date)
-    placeholders['section'] = item.section || ''
-    placeholders['title'] = item.title
-    placeholders['note'] = note
-    placeholders['idnote'] = note.empty? ? '' : "\n#{note.map { |l| "\t\t#{l.strip}  " }.join("\n")}"
-    placeholders['odnote'] = note.empty? ? '' : "\n#{note.map { |l| "#{l.strip}  " }.join("\n")}"
-
-    chompnote = []
-    unless note.empty?
-      chompnote = note.map do |l|
-        l.gsub(/\n+/, ' ').gsub(/(^\s*|\s*$)/, '').gsub(/\s+/, ' ')
-      end
-    end
-    placeholders['chompnote'] = chompnote.join(' ')
-
-    template = opt[:template].dup
-    note_rx = /(?i-m)(?x:^([\s\S]*?)
-                (%(?:[io]d|(?:\^[\s\S])?
-                (?:(?:[ _t]|[^a-z0-9])?\d+)?
-                (?:[\s\S][ _t]?)?)?note)
-                ([\s\S]*?)$)/
-    template.sub!(note_rx, '\1\3\2')
-    output = Doing::TemplateString.new(template,
-                                       color: flag,
-                                       placeholders: placeholders,
-                                       reset: reset,
-                                       tags_color: opt[:tags_color],
-                                       wrap_width: opt[:wrap_width]).colored
-
-    output.gsub!(/(?<!\\)%(\S)?hr(_under)?/) do
-      o = ''
-      TTY::Screen.columns.to_i.times do
-        char = Regexp.last_match(2).nil? ? '-' : '_'
-        char = Regexp.last_match(1).nil? ? char : Regexp.last_match(1)
-        o += char
-      end
-      o
-    end
-    output.gsub!(/(?<!\\)%n/, "\n")
-    output.gsub!(/(?<!\\)%t/, "\t")
-
-    output.gsub!(/\\%/, '%')
-
-    output.highlight_search!(opt[:search]) if opt[:output] =~ /^temp/ && opt[:search] && !opt[:not] && opt[:hilite]
-
-    out += "#{output}\n"
-  end
-
-  # Doing.logger.debug('Template Export:', "#{items.count} items output to template #{opt[:output]}")
-  if opt[:totals]
-    out += wwid.tag_times(format: Doing.setting('timer_format').to_sym,
-                          sort_by: opt[:sort_tags],
-                          sort_order: opt[:tag_order])
-  end
-  Doing.logger.benchmark(:template_render, :finish)
-  out
-end
-
+
@@ -495,29 +231,7 @@

-

- - - - -
-
-
-
-13
-14
-15
-16
-17
-
-
# File 'lib/doing/plugins/export/template_export.rb', line 13
-
-def self.settings
-  {
-    trigger: 'template'
-  }
-end
-
+
@@ -525,7 +239,7 @@

diff --git a/docs/doc/Doing/TemplateString.html b/docs/doc/Doing/TemplateString.html index 41f610b6..ff251c37 100644 --- a/docs/doc/Doing/TemplateString.html +++ b/docs/doc/Doing/TemplateString.html @@ -522,35 +522,7 @@

-
- - - - -
-
-
-
-11
-12
-13
-14
-15
-16
-17
-18
-
-
# File 'lib/doing/template_string.rb', line 11
-
-def initialize(string, placeholders: {}, force_color: false, wrap_width: 0, color: '', tags_color: '', reset: '')
-  Color.coloring = true if force_color
-  @colors = nil
-  @original = string
-  super(Color.reset + string)
-
-  placeholders.each { |k, v| fill(k, v, wrap_width: wrap_width, color: color, tags_color: tags_color) }
-end
-
+ @@ -579,25 +551,7 @@

-
- - - - -
-
-
-
-8
-9
-10
-
-
# File 'lib/doing/template_string.rb', line 8
-
-def original
-  @original
-end
-
+ @@ -647,35 +601,7 @@

- - - - - -
-
-
-
-88
-89
-90
-91
-92
-93
-94
-95
-
-
# File 'lib/doing/template_string.rb', line 88
-
-def apply_colors(color_array)
-  str = dup
-  color_array.reverse.each do |color|
-    c = color[:color].empty? ? Color.send(color[:name]) : color[:color]
-    str.insert(color[:index], c)
-  end
-  str
-end
-
+
@@ -714,27 +640,7 @@

-

- - - - -
-
-
-
-41
-42
-43
-44
-
-
# File 'lib/doing/template_string.rb', line 41
-
-def colored
-  reparse
-  parsed_colors[:string].apply_colors(parsed_colors[:colors])
-end
-
+
@@ -773,31 +679,7 @@

-

- - - - -
-
-
-
-25
-26
-27
-28
-29
-30
-
-
# File 'lib/doing/template_string.rb', line 25
-
-def colors?
-  scan(/%([a-z]+)/).each do
-    return true if Regexp.last_match(1).validate_color
-  end
-  false
-end
-
+
@@ -809,191 +691,7 @@

-

- - - - -
-
-
-
-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
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-
-
# File 'lib/doing/template_string.rb', line 97
-
-def fill(placeholder, value, wrap_width: 0, color: '', tags_color: '', reset: '')
-  reparse
-  rx = /(?mi)(?<!\\)%(?<width>-?\d+)?(?:\^(?<mchar>.))?(?:(?<ichar>[ _t]|[^a-z0-9])(?<icount>\d+))?(?<prefix>.[ _t]?)?#{placeholder.sub(/^%/, '')}(?<after>.*?)$/
-  ph = raw.match(rx)
-
-  return unless ph
-  placeholder_offset = ph.begin(0)
-  last_colors = parsed_colors[:colors].select { |v| v[:index] <= placeholder_offset + 4 }
-
-  last_color = last_colors.map { |v| v[:color] }.pop(3).join('')
-
-  sub!(rx) do
-    m = Regexp.last_match
-
-    after = m['after']
-
-    if !value.good?
-      after
-    else
-      pad = m['width'].to_i
-      mark = m['mchar'] || ''
-      if placeholder == 'shortdate' && m['width'].nil?
-        fmt_string = Doing.setting('shortdate_format.older', '%m/%d/%y %_I:%M%P', exact: true)
-        pad = Date.today.strftime(fmt_string).length
-      end
-      indent = nil
-      if m['ichar']
-        char = m['ichar'] =~ /t/ ? "\t" : ' '
-        indent = char * m['icount'].to_i
-      end
-      indent ||= placeholder =~ /^title/ ? '' : "\t"
-      prefix = m['prefix']
-
-      if placeholder =~ /^tags/
-        prefix ||= ''
-        value = value.map { |t| "#{prefix}#{t.sub(/^#{prefix}?/, '')}" }.join(' ')
-        prefix = ''
-      end
-
-      if placeholder =~ /^title/
-        color = last_color + color
-
-        if wrap_width.positive? || pad.positive?
-          width = pad.positive? ? pad : wrap_width
-
-          out = value.gsub(/%/, '\%').strip.wrap(width,
-                                                 pad: pad,
-                                                 indent: indent,
-                                                 offset: placeholder_offset,
-                                                 prefix: prefix,
-                                                 color: color,
-                                                 after: after,
-                                                 reset: reset,
-                                                 pad_first: false)
-          out.highlight_tags!(tags_color, last_color: color) if tags_color && !tags_color.empty?
-          out
-        else
-          out = format("%s%s%#{pad}s%s", prefix, color, value.gsub(/%/, '\%').sub(/\s*$/, ''), after)
-          out.highlight_tags!(tags_color, last_color: color) if tags_color && !tags_color.empty?
-          out
-        end
-      elsif placeholder =~ /^note/
-        if wrap_width.positive? || pad.positive?
-          width = pad.positive? ? pad : wrap_width
-          outstring = value.map do |l|
-            if l.empty?
-              '  '
-            else
-              line = l.gsub(/%/, '\%').strip.wrap(width, pad: pad, indent: indent, offset: 0, prefix: prefix, color: last_color, after: after, reset: reset, pad_first: true)
-              line.highlight_tags!(tags_color, last_color: last_color) unless !tags_color || !tags_color.good?
-              "#{line}  "
-            end
-          end.join("\n")
-          "\n#{last_color}#{mark}#{outstring}  "
-        else
-          out = format("\n%s%s%s%#{pad}s%s", indent, prefix, last_color, value.join("\n#{indent}#{prefix}").gsub(/%/, '\%').sub(/\s*$/, ''), after)
-          out.highlight_tags!(tags_color, last_color: last_color) if tags_color && !tags_color.empty?
-          out
-        end
-      else
-        format("%s%#{pad}s%s", prefix, value.gsub(/%/, '\%').sub(/\s*$/, ''), after)
-      end
-    end
-  end
-  @parsed_colors = parse_colors
-end
-
+

@@ -1033,51 +731,7 @@

-

- - - - -
-
-
-
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-
-
# File 'lib/doing/template_string.rb', line 64
-
-def parse_colors
-  working = dup
-  color_array = []
-
-  scan(/(?<!\\)(%((?:[fb]g?)?#[a-fA-F0-9]{6}|[a-z]+))/).each do |color|
-    valid_color = color[1].validate_color
-    next unless valid_color
-
-    idx = working.match(/(?<!\\)%#{valid_color}/).begin(0)
-    color = Color.attributes.include?(valid_color.to_sym) ? Color.send(valid_color) : Color.rgb(valid_color)
-    color_array.push({ name: valid_color, color: color, index: idx })
-    working.sub!(/(?<!\\)%#{valid_color}/, '')
-  end
-
-  { string: working, colors: color_array }
-end
-
+
@@ -1089,25 +743,7 @@

-

- - - - -
-
-
-
-55
-56
-57
-
-
# File 'lib/doing/template_string.rb', line 55
-
-def parsed_colors
-  @parsed_colors ||= parse_colors
-end
-
+
@@ -1146,25 +782,7 @@

-

- - - - -
-
-
-
-51
-52
-53
-
-
# File 'lib/doing/template_string.rb', line 51
-
-def raw
-  parsed_colors[:string].uncolor
-end
-
+
@@ -1176,25 +794,7 @@

-

- - - - -
-
-
-
-32
-33
-34
-
-
# File 'lib/doing/template_string.rb', line 32
-
-def reparse
-  @parsed_colors = nil
-end
-
+
@@ -1202,7 +802,7 @@

diff --git a/docs/doc/Doing/TimingImport.html b/docs/doc/Doing/TimingImport.html index 2efc9dcd..0c1fc332 100644 --- a/docs/doc/Doing/TimingImport.html +++ b/docs/doc/Doing/TimingImport.html @@ -255,169 +255,7 @@

- - - - - -
-
-
-
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-
-
# File 'lib/doing/plugins/import/timing_import.rb', line 25
-
-def self.import(wwid, path, options: {})
-  exit_now! 'Path to JSON report required' if path.nil?
-  section = options[:section] || Doing.setting('current_section')
-  options[:no_overlap] ||= false
-  options[:autotag] ||= Doing.auto_tag
-  wwid.content.add_section(section) unless wwid.content.section?(section)
-
-  add_tags = options[:tag] ? options[:tag].split(/[ ,]+/).map { |t| t.sub(/^@?/, '') } : []
-  prefix = options[:prefix] || '[Timing.app]'
-  exit_now! 'File not found' unless File.exist?(File.expand_path(path))
-
-  data = JSON.parse(IO.read(File.expand_path(path)))
-  new_items = []
-  data.each do |entry|
-    # Only process task entries
-    next if entry.key?('activityType') && entry['activityType'] != 'Task'
-    # Only process entries with a start and end date
-    next unless entry.key?('startDate') && entry.key?('endDate')
-
-    # Round down seconds and convert UTC to local time
-    start_time = Time.parse(entry['startDate'].sub(/:\d\dZ$/, ':00Z')).getlocal
-    end_time = Time.parse(entry['endDate'].sub(/:\d\dZ$/, ':00Z')).getlocal
-    next unless start_time && end_time
-
-    tags = entry['project'].split(//).map { |proj| proj.gsub(/[^a-z0-9]+/i, '').downcase }
-    tags.concat(add_tags)
-    title = "#{prefix} "
-    title += entry.key?('activityTitle') && entry['activityTitle'] != '(Untitled Task)' ? entry['activityTitle'] : 'Working on'
-    tags.each do |tag|
-      if title =~ /\b#{tag}\b/i
-        title.sub!(/\b#{tag}\b/i, "@#{tag}")
-      else
-        title += " @#{tag}"
-      end
-    end
-    title = wwid.autotag(title) if options[:autotag]
-    title += " @done(#{end_time.strftime('%Y-%m-%d %H:%M')})"
-    title.gsub!(/ +/, ' ')
-    title.strip!
-    new_item = Item.new(start_time, title, section)
-    new_item.note.add(entry['notes']) if entry.key?('notes')
-
-    is_match = true
-
-    if options[:search]
-      is_match = new_item.search(options[:search], case_type: options[:case], negate: options[:not])
-    end
-
-    if is_match && options[:date_filter]
-      is_match = start_time > options[:date_filter][0] && start_time < options[:date_filter][1]
-      is_match = options[:not] ? !is_match : is_match
-    end
-
-    new_items.push(new_item) if is_match
-  end
-  total = new_items.count
-  skipped = data.count - total
-  Doing.logger.debug('Skipped:' , %(#{skipped} items, invalid type or no time interval)) if skipped.positive?
-
-  new_items = wwid.filter_items(new_items, opt: options)
-  filtered = skipped - new_items.count
-  Doing.logger.debug('Skipped:' , %(#{filtered} items that didn't match filter criteria)) if filtered.positive?
-
-  new_items = wwid.dedup(new_items, no_overlap: options[:no_overlap])
-  dups = filtered - new_items.count
-  Doing.logger.debug('Skipped:' , %(#{dups} items with overlapping times)) if dups.positive?
-
-  new_items.map { |item| Hooks.trigger :pre_entry_add, self, item }
-
-  wwid.content.concat(new_items)
-
-  new_items.map { |item| Hooks.trigger :post_entry_added, self, item }
-
-  Doing.logger.info('Imported:', %(#{new_items.count} items to #{section}))
-end
-
+
@@ -429,29 +267,7 @@

-

- - - - -
-
-
-
-11
-12
-13
-14
-15
-
-
# File 'lib/doing/plugins/import/timing_import.rb', line 11
-
-def self.settings
-  {
-    trigger: 'tim(?:ing)?'
-  }
-end
-
+

@@ -459,7 +275,7 @@

diff --git a/docs/doc/Doing/Types.html b/docs/doc/Doing/Types.html index a06da3e3..d7f8441a 100644 --- a/docs/doc/Doing/Types.html +++ b/docs/doc/Doing/Types.html @@ -241,7 +241,7 @@

diff --git a/docs/doc/Doing/Util.html b/docs/doc/Doing/Util.html index 22def539..0481ecc5 100644 --- a/docs/doc/Doing/Util.html +++ b/docs/doc/Doing/Util.html @@ -505,45 +505,7 @@

-

- - - - -
-
-
-
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-
-
# File 'lib/doing/util.rb', line 149
-
-def args_for_editor(editor)
-  return editor if editor =~ /-\S/
-
-  args = case editor
-         when /^(subl|code|mate)$/
-           ['-w']
-         when /^(vim|mvim)$/
-           ['-f']
-         else
-           []
-         end
-  "#{editor} #{args.join(' ')}"
-end
-
+
@@ -623,25 +585,7 @@

-

- - - - -
-
-
-
-58
-59
-60
-
-
# File 'lib/doing/util.rb', line 58
-
-def deep_merge_hashes(master_hash, other_hash)
-  deep_merge_hashes!(master_hash.clone, other_hash)
-end
-
+
@@ -722,33 +666,7 @@

-

- - - - -
-
-
-
-77
-78
-79
-80
-81
-82
-83
-
-
# File 'lib/doing/util.rb', line 77
-
-def deep_merge_hashes!(target, overwrite)
-  merge_values(target, overwrite)
-  merge_default_proc(target, overwrite)
-  duplicate_frozen_values(target)
-
-  target
-end
-
+
@@ -760,25 +678,7 @@

-

- - - - -
-
-
-
-141
-142
-143
-
-
# File 'lib/doing/util.rb', line 141
-
-def default_editor
-  @default_editor ||= find_default_editor
-end
-
+
@@ -812,35 +712,7 @@

-

- - - - -
-
-
-
-85
-86
-87
-88
-89
-90
-91
-92
-
-
# File 'lib/doing/util.rb', line 85
-
-def duplicable?(obj)
-  case obj
-  when nil, false, true, Symbol, Numeric
-    false
-  else
-    true
-  end
-end
-
+
@@ -852,29 +724,7 @@

-

- - - - -
-
-
-
-44
-45
-46
-47
-48
-
-
# File 'lib/doing/util.rb', line 44
-
-def duplicate_frozen_values(target)
-  target.each do |key, val|
-    target[key] = val.dup if val.frozen? && duplicable?(val)
-  end
-end
-
+
@@ -886,25 +736,7 @@

-

- - - - -
-
-
-
-145
-146
-147
-
-
# File 'lib/doing/util.rb', line 145
-
-def editor_with_args
-  args_for_editor(default_editor)
-end
-
+
@@ -945,29 +777,7 @@

-

- - - - -
-
-
-
-21
-22
-23
-24
-25
-
-
# File 'lib/doing/util.rb', line 21
-
-def exec_available(cli)
-  return false unless cli.good?
-
-  !TTY::Which.which(cli).nil?
-end
-
+
@@ -979,113 +789,7 @@

-

- - - - -
-
-
-
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-
-
# File 'lib/doing/util.rb', line 163
-
-def find_default_editor(editor_for = 'default')
-  # return nil unless $stdout.isatty || ENV['DOING_EDITOR_TEST']
-
-  return ENV['EDITOR'] if ENV['DOING_EDITOR_TEST']
-
-  editor_config = Doing.setting('editors')
-
-  if editor_config.is_a?(String)
-    msg = "Please update your configuration, 'editors' should be a mapping."
-    msg << ' Delete the key and run `doing config --update`.'
-    Doing.logger.warn('Deprecated:', msg)
-    return editor_config
-  end
-
-  if editor_config[editor_for]
-    editor = editor_config[editor_for]
-    Doing.logger.debug('Editor:', "Using #{editor} from config 'editors.#{editor_for}' for #{editor_for}")
-    return editor if editor.good?
-  end
-
-  if editor_for != 'editor' && editor_config['default']
-    editor = editor_config['default']
-    Doing.logger.debug('Editor:', "Using #{editor} from config: 'editors.default' for #{editor_for}")
-    return editor if editor.good?
-  end
-
-  editor ||= ENV['DOING_EDITOR'] || ENV['GIT_EDITOR'] || ENV['EDITOR']
-
-  if editor.good?
-    Doing.logger.debug('Editor:', "Found editor in environment variables: #{editor} for #{editor_for}")
-    return editor
-  end
-
-  Doing.logger.debug('Editor:', 'No EDITOR environment variable, testing available editors')
-  editors = %w[vim vi code subl mate mvim nano emacs]
-  editors.each do |ed|
-    try = TTY::Which.which(ed)
-    if try
-      Doing.logger.debug('Editor:', "Using editor #{try} for #{editor_for}")
-      return try
-    end
-
-    Doing.logger.debug('Editor:', "#{ed} not available")
-  end
-
-  nil
-end
-
+
@@ -1115,27 +819,7 @@

Examples:

- - - - - -
-
-
-
-33
-34
-35
-36
-
-
# File 'lib/doing/util.rb', line 33
-
-def first_available_exec(*commands)
-  commands.compact.map(&:strip).reject(&:empty?).uniq
-          .find { |cmd| exec_available(cmd.split.first) }
-end
-
+
@@ -1169,25 +853,7 @@

-

- - - - -
-
-
-
-94
-95
-96
-
-
# File 'lib/doing/util.rb', line 94
-
-def mergable?(value)
-  value.is_a?(Hash)
-end
-
+
@@ -1199,29 +865,7 @@

-

- - - - -
-
-
-
-38
-39
-40
-41
-42
-
-
# File 'lib/doing/util.rb', line 38
-
-def merge_default_proc(target, overwrite)
-  return unless target.is_a?(Hash) && overwrite.is_a?(Hash) && target.default_proc.nil?
-
-  target.default_proc = overwrite.default_proc
-end
-
+
@@ -1233,41 +877,7 @@

-

- - - - -
-
-
-
-98
-99
-100
-101
-102
-103
-104
-105
-106
-107
-108
-
-
# File 'lib/doing/util.rb', line 98
-
-def merge_values(target, overwrite)
-  target.merge!(overwrite) do |_key, old_val, new_val|
-    if new_val.nil?
-      old_val
-    elsif mergable?(old_val) && mergable?(new_val)
-      deep_merge_hashes(old_val, new_val)
-    else
-      new_val
-    end
-  end
-end
-
+
@@ -1279,25 +889,7 @@

-

- - - - -
-
-
-
-137
-138
-139
-
-
# File 'lib/doing/util.rb', line 137
-
-def safe_load_file(filename)
-  SafeYAML.load_file(filename) || {}
-end
-
+
@@ -1309,33 +901,7 @@

-

- - - - -
-
-
-
-8
-9
-10
-11
-12
-13
-14
-
-
# File 'lib/doing/util.rb', line 8
-
-def user_home
-  if Dir.respond_to?('home')
-    Dir.home
-  else
-    File.expand_path('~')
-  end
-end
-
+
@@ -1408,57 +974,7 @@

-

- - - - -
-
-
-
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-130
-131
-132
-133
-134
-135
-
-
# File 'lib/doing/util.rb', line 117
-
-def write_to_file(file, content, backup: true)
-  unless file
-    puts content
-    return
-  end
-  Doing.logger.benchmark(:write_file, :start)
-  file = File.expand_path(file)
-
-  Backup.write_backup(file) if backup
-
-  File.open(file, 'w+') do |f|
-    f.puts content
-    Doing.logger.debug('Write:', "File written: #{file}")
-  end
-  Doing.logger.benchmark(:_post_write_hook, :start)
-  Hooks.trigger :post_write, file
-  Doing.logger.benchmark(:_post_write_hook, :finish)
-  Doing.logger.benchmark(:write_file, :finish)
-end
-
+ @@ -1466,7 +982,7 @@

diff --git a/docs/doc/Doing/Util/Backup.html b/docs/doc/Doing/Util/Backup.html index 2d66d1b4..e7e8f8de 100644 --- a/docs/doc/Doing/Util/Backup.html +++ b/docs/doc/Doing/Util/Backup.html @@ -361,31 +361,7 @@

- - - - - -
-
-
-
-33
-34
-35
-36
-37
-38
-
-
# File 'lib/doing/util_backup.rb', line 33
-
-def last_backup(filename = nil, count: 1)
-  filename ||= Doing.setting('doing_file')
-
-  backup = get_backups(filename).slice(count - 1)
-  backup.nil? ? nil : File.join(backup_dir, backup)
-end
-
+
@@ -428,39 +404,7 @@

-

- - - - -
-
-
-
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-
-
# File 'lib/doing/util_backup.rb', line 16
-
-def prune_backups(filename, limit = 10)
-  backups = get_backups(filename)
-  return unless backups.count > limit
-
-  backups[limit..-1].each do |file|
-    FileUtils.rm(File.join(backup_dir, file))
-  end
-
-  clear_redo(filename)
-end
-
+
@@ -516,65 +460,7 @@

-

- - - - -
-
-
-
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-
-
# File 'lib/doing/util_backup.rb', line 67
-
-def redo_backup(filename = nil, count: 1)
-  filename ||= Doing.setting('doing_file')
-
-  undones = Dir.glob("undone*#{File.basename(filename)}", base: backup_dir).sort.reverse
-  total = undones.count
-  count = total if count > total
-
-  skipped = undones.slice!(0, count)
-  undone = skipped.pop
-
-  raise HistoryLimitError, 'End of redo history' if undone.nil?
-
-  redo_file = File.join(backup_dir, undone)
-
-  move_backup(redo_file, filename)
-
-  skipped.each do |f|
-    FileUtils.mv(File.join(backup_dir, f), File.join(backup_dir, f.sub(/^undone/, '')))
-  end
-
-  Doing.logger.warn('File update:', "restored undo step #{count}/#{total}")
-  Doing.logger.debug('Backup:', "#{total - skipped.count - 1} redos remaining")
-end
-
+
@@ -632,47 +518,7 @@

-

- - - - -
-
-
-
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-
-
# File 'lib/doing/util_backup.rb', line 47
-
-def restore_last_backup(filename = nil, count: 1)
-  Doing.logger.benchmark(:restore_backup, :start)
-  filename ||= Doing.setting('doing_file')
-
-  backup_file = last_backup(filename, count: count)
-  raise HistoryLimitError, 'End of undo history' if backup_file.nil?
-
-  save_undone(filename)
-  move_backup(backup_file, filename)
-
-  prune_backups_after(File.basename(backup_file))
-  Doing.logger.warn('File update:', "restored from #{backup_file}")
-  Doing.logger.benchmark(:restore_backup, :finish)
-end
-
+
@@ -729,53 +575,7 @@

-

- - - - -
-
-
-
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-
-
# File 'lib/doing/util_backup.rb', line 135
-
-def select_backup(filename = nil)
-  filename ||= Doing.setting('doing_file')
-
-  options = get_backups(filename).each_with_object([]) do |file, arr|
-    d, _base = date_of_backup(file)
-    next if d.nil?
-    arr.push("#{d.time_ago}\t#{File.join(backup_dir, file)}")
-  end
-
-  raise MissingBackupFile, 'No backup files to load' if options.empty?
-
-  backup_file = show_menu(options, filename)
-  Util.write_to_file(File.join(backup_dir, "undone___#{File.basename(filename)}"), IO.read(filename), backup: false)
-  move_backup(backup_file, filename)
-  prune_backups_after(File.basename(backup_file))
-  Doing.logger.warn('File update:', "restored from #{backup_file}")
-end
-
+
@@ -832,81 +632,7 @@

-

- - - - -
-
-
-
-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
-
-
# File 'lib/doing/util_backup.rb', line 97
-
-def select_redo(filename = nil)
-  filename ||= Doing.setting('doing_file')
-
-  undones = Dir.glob("undone*#{File.basename(filename)}", base: backup_dir).sort
-  raise HistoryLimitError, 'End of redo history' if undones.empty?
-
-  total = undones.count
-  options = undones.each_with_object([]) do |file, arr|
-    d, _base = date_of_backup(file)
-    next if d.nil?
-
-    arr.push("#{d.time_ago}\t#{File.join(backup_dir, file)}")
-  end
-  raise MissingBackupFile, 'No backup files to load' if options.empty?
-
-  backup_file = show_menu(options, filename)
-  idx = undones.index(File.basename(backup_file))
-  skipped = undones.slice!(idx, undones.count - idx)
-  undone = skipped.shift
-
-  redo_file = File.join(backup_dir, undone)
-
-  move_backup(redo_file, filename)
-
-  skipped.each do |f|
-    FileUtils.mv(File.join(backup_dir, f), File.join(backup_dir, f.sub(/^undone/, '')))
-  end
-
-  Doing.logger.warn('File update:', "restored undo step #{idx}/#{total}")
-  Doing.logger.debug('Backup:', "#{total - skipped.count - 1} redos remaining")
-end
-
+
@@ -950,61 +676,7 @@

-

- - - - -
-
-
-
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-
-
# File 'lib/doing/util_backup.rb', line 159
-
-def write_backup(filename = nil)
-  Doing.logger.benchmark(:_write_backup, :start)
-  filename ||= Doing.setting('doing_file')
-
-  unless File.exist?(filename)
-    Doing.logger.debug('Backup:', "original file doesn't exist (#{filename})")
-    return
-  end
-
-  backup_file = File.join(backup_dir, "#{timestamp_filename}___#{File.basename(filename)}")
-  # compressed = Zlib::Deflate.deflate(content)
-  # Zlib::GzipWriter.open(backup_file + '.gz') do |gz|
-  #   gz.write(IO.read(filename))
-  # end
-
-  FileUtils.cp(filename, backup_file)
-
-  prune_backups(filename, Doing.setting('history_size').to_i)
-  clear_undone(filename)
-  Doing.logger.benchmark(:_write_backup, :finish)
-end
-
+ @@ -1012,7 +684,7 @@

diff --git a/docs/doc/Doing/Version.html b/docs/doc/Doing/Version.html index 10138ec3..08f7c43b 100644 --- a/docs/doc/Doing/Version.html +++ b/docs/doc/Doing/Version.html @@ -351,25 +351,7 @@

-
- - - - -
-
-
-
-8
-9
-10
-
-
# File 'lib/doing/changelog/version.rb', line 8
-
-def initialize(string)
-  @maj, @min, @patch = version_to_a(string)
-end
-
+ @@ -398,25 +380,7 @@

-
- - - - -
-
-
-
-6
-7
-8
-
-
# File 'lib/doing/changelog/version.rb', line 6
-
-def maj
-  @maj
-end
-
+ @@ -440,25 +404,7 @@

-
- - - - -
-
-
-
-6
-7
-8
-
-
# File 'lib/doing/changelog/version.rb', line 6
-
-def min
-  @min
-end
-
+ @@ -482,25 +428,7 @@

-
- - - - -
-
-
-
-6
-7
-8
-
-
# File 'lib/doing/changelog/version.rb', line 6
-
-def patch
-  @patch
-end
-
+ @@ -519,139 +447,7 @@

-

- - - - -
-
-
-
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-
-
# File 'lib/doing/changelog/version.rb', line 40
-
-def compare(other, comp, inclusive: false)
-  case comp
-  when :older
-    if @maj <= other.maj
-      if @maj < other.maj
-        true
-      elsif @maj == other.maj && (other.min.nil? || @min < other.min)
-        true
-      elsif @maj == other.maj && @min == other.min
-        if other.patch.nil?
-          false
-        else
-          inclusive ? @patch <= other.patch : @patch < other.patch
-        end
-      else
-        false
-      end
-    else
-      false
-    end
-  when :newer
-    if @maj >= other.maj
-      if @maj > other.maj
-        true
-      elsif @maj == other.maj && (other.min.nil? || @min > other.min)
-        true
-      elsif @maj == other.maj && @min == other.min
-        if other.patch.nil?
-          false
-        else
-          inclusive ? @patch >= other.patch : @patch > other.patch
-        end
-      else
-        false
-      end
-    else
-      false
-    end
-  when :equal
-    if @maj == other.maj
-      if other.min.nil?
-        true
-      elsif wild?(other.min)
-        @min.to_s =~ /^#{other.min}/ ? true : false
-      else
-        if @min == other.min
-          if other.patch.nil?
-            true
-          elsif wild?(other.patch)
-            @patch.to_s =~ /^#{other.patch}/ ? true : false
-          else
-            @patch == other.patch
-          end
-        else
-          false
-        end
-      end
-    end
-  end
-end
-
+
@@ -663,25 +459,7 @@

-

- - - - -
-
-
-
-101
-102
-103
-
-
# File 'lib/doing/changelog/version.rb', line 101
-
-def to_s
-  "#{@maj}.#{@min || 0}.#{@patch || 0}"
-end
-
+
@@ -693,63 +471,7 @@

-

- - - - -
-
-
-
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-
-
# File 'lib/doing/changelog/version.rb', line 12
-
-def version_to_a(string)
-  raise 'Version not a string' unless string.is_a?(String)
-
-  v = string.match(/(?<maj>\d+)(?:\.(?<min>[\d*?]+))?(?:\.(?<patch>[\d*?]+))?/)
-
-  raise 'Error parsing semantic version string' if v.nil?
-
-  maj = v['maj'].to_i
-  min = case v['min']
-        when /[*?]/
-          v['min'].sub(/(\d+)?[^\d]/, '\1\d+')
-        when /^[0-9]+$/
-          v['min'].to_i
-        end
-  pat = case v['patch']
-        when /[*?]/
-          v['patch'].sub(/(\d+)?[^\d]/, '\1\d+')
-        when /^[0-9]+$/
-          v['patch'].to_i
-        end
-  [maj, min, pat]
-end
-
+
@@ -783,25 +505,7 @@

-

- - - - -
-
-
-
-35
-36
-37
-
-
# File 'lib/doing/changelog/version.rb', line 35
-
-def wild?(val)
-  val.is_a?(String)
-end
-
+ @@ -809,7 +513,7 @@

diff --git a/docs/doc/Doing/WWID.html b/docs/doc/Doing/WWID.html index aeb49aa1..a3054c14 100644 --- a/docs/doc/Doing/WWID.html +++ b/docs/doc/Doing/WWID.html @@ -1634,31 +1634,7 @@

-
- - - - -
-
-
-
-55
-56
-57
-58
-59
-60
-
-
# File 'lib/doing/wwid/wwid.rb', line 55
-
-def initialize
-  @timers = {}
-  @recorded_items = []
-  @content = Items.new
-  Doing.auto_tag = true
-end
-
+ @@ -1687,25 +1663,7 @@

-
- - - - -
-
-
-
-27
-28
-29
-
-
# File 'lib/doing/wwid/wwid.rb', line 27
-
-def additional_configs
-  @additional_configs
-end
-
+ @@ -1729,25 +1687,7 @@

-
- - - - -
-
-
-
-42
-43
-44
-
-
# File 'lib/doing/wwid/wwid.rb', line 42
-
-def config
-  @config
-end
-
+ @@ -1771,25 +1711,7 @@

-
- - - - -
-
-
-
-45
-46
-47
-
-
# File 'lib/doing/wwid/wwid.rb', line 45
-
-def config_file
-  @config_file
-end
-
+ @@ -1813,25 +1735,7 @@

-
- - - - -
-
-
-
-36
-37
-38
-
-
# File 'lib/doing/wwid/wwid.rb', line 36
-
-def content
-  @content
-end
-
+ @@ -1855,25 +1759,7 @@

-
- - - - -
-
-
-
-30
-31
-32
-
-
# File 'lib/doing/wwid/wwid.rb', line 30
-
-def current_section
-  @current_section
-end
-
+ @@ -1897,25 +1783,7 @@

-
- - - - -
-
-
-
-48
-49
-50
-
-
# File 'lib/doing/wwid/wwid.rb', line 48
-
-def default_option
-  @default_option
-end
-
+ @@ -1939,25 +1807,7 @@

-
- - - - -
-
-
-
-33
-34
-35
-
-
# File 'lib/doing/wwid/wwid.rb', line 33
-
-def doing_file
-  @doing_file
-end
-
+ @@ -1981,25 +1831,7 @@

-
- - - - -
-
-
-
-39
-40
-41
-
-
# File 'lib/doing/wwid/wwid.rb', line 39
-
-def initial_content
-  @initial_content
-end
-
+ @@ -2175,487 +2007,7 @@

- - - - - -
-
-
-
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-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
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-
-
# File 'lib/doing/wwid/interactive.rb', line 66
-
-def act_on(items, opt)
-  opt ||= {}
-  actions = %i[editor delete tag flag finish cancel archive output save_to again resume]
-  has_action = false
-  single = items.count == 1
-
-  actions.each do |a|
-    if opt[a]
-      has_action = true
-      break
-    end
-  end
-
-  unless has_action
-    actions = [
-      'add tag',
-      'remove tag',
-      'autotag',
-      'cancel',
-      'delete',
-      'finish',
-      'flag',
-      'archive',
-      'move',
-      'edit',
-      'output formatted'
-    ]
-
-    actions.concat(['resume/repeat', 'begin/reset']) if items.count == 1
-
-    choice = Prompt.choose_from(actions.map(&:titlecase),
-                                prompt: 'What do you want to do with the selected items? > ',
-                                multiple: true,
-                                sorted: false,
-                                fzf_args: ["--height=#{actions.count + 3}", '--tac', '--no-sort', '--info=hidden'])
-    return unless choice
-
-    to_do = choice.strip.split(/\n/).map(&:downcase)
-
-    to_do.each do |action|
-      action = 'resume' if action =~ /^resume/i
-      action = 'reset' if action =~ /^begin/i
-
-      case action
-      when /(resume|reset|autotag|archive|delete|finish|cancel|flag)/
-        opt[action.to_sym] = true
-      when /edit/
-        opt[:editor] = true
-      when /(add|remove) tag/
-        type = action =~ /^add/ ? 'add' : 'remove'
-        raise InvalidArgument, "'add tag' and 'remove tag' can not be used together" if opt[:tag]
-
-        tags = type == 'add' ? all_tags(@content) : all_tags(items)
-
-        add_msg = type == 'add' ? ', include values with tag(value)' : ''
-        puts "#{yellow}Separate multiple tags with spaces, hit tab to complete known tags#{add_msg}"
-        puts "#{boldgreen}Available tags: #{boldwhite}#{tags.sort.map(&:add_at).join(', ')}" if type == 'remove'
-        tag = Prompt.read_line(prompt: "Tags to #{type}", completions: tags)
-
-        # print "#{yellow("Tag to #{type}: ")}#{reset}"
-        # tag = $stdin.gets
-        next if tag =~ /^ *$/
-
-        opt[:tag] = tag.strip.sub(/^@/, '')
-        opt[:remove] = true if type == 'remove'
-      when /output formatted/
-        plugins = Plugins.available_plugins(type: :export).sort
-        output_format = Prompt.choose_from(plugins,
-                                           prompt: 'Which output format? > ',
-                                           fzf_args: [
-                                             "--height=#{plugins.count + 3}",
-                                             '--tac',
-                                             '--no-sort',
-                                             '--info=hidden'
-                                           ])
-        next if output_format =~ /^ *$/
-
-        raise UserCancelled unless output_format
-
-        opt[:output] = output_format.strip
-        res = opt[:force] ? false : Prompt.yn('Save to file?', default_response: 'n')
-        if res
-          # print "#{yellow('File path/name: ')}#{reset}"
-          # filename = $stdin.gets.strip
-          filename = Prompt.read_line(prompt: 'File path/name')
-          next if filename.empty?
-
-          opt[:save_to] = filename
-        end
-      when /move/
-        section = choose_section.strip
-        opt[:move] = section.strip unless section =~ /^ *$/
-      end
-    end
-  end
-
-  if opt[:resume] || opt[:reset]
-    raise InvalidArgument, 'resume and restart can only be used on a single entry' if items.count > 1
-
-    item = items[0]
-    if opt[:resume] && !opt[:reset]
-      repeat_item(item, { editor: opt[:editor] }) # hooked
-    elsif opt[:reset]
-      res = Prompt.enter_text('Start date (blank for current time)', default_response: '')
-      date = if res =~ /^ *$/
-               Time.now
-             else
-               res.chronify(guess: :begin)
-             end
-
-      res = if item.tags?('done', :and) && !opt[:resume]
-              opt[:force] ? true : Prompt.yn('Remove @done tag?', default_response: 'y')
-            else
-              opt[:resume]
-            end
-      old_item = item.clone
-      new_entry = reset_item(item, date: date, resume: res)
-      @content.update_item(item, new_entry)
-      Hooks.trigger :post_entry_updated, self, new_entry, old_item
-    end
-    write(@doing_file)
-
-    return
-  end
-
-  if opt[:delete]
-    delete_items(items, force: opt[:force]) # hooked
-    write(@doing_file)
-
-    return
-  end
-
-  if opt[:flag]
-    tag = Doing.setting('marker_tag', 'flagged')
-    items.map! do |i|
-      old_item = i.clone
-      i.tag(tag, date: false, remove: opt[:remove], single: single)
-      Hooks.trigger :post_entry_updated, self, i, old_item
-    end
-  end
-
-  if opt[:finish] || opt[:cancel]
-    tag = 'done'
-    items.map! do |i|
-      next unless i.should_finish?
-
-      old_item = i.clone
-      should_date = !opt[:cancel] && i.should_time?
-      i.tag(tag, date: should_date, remove: opt[:remove], single: single)
-      Hooks.trigger :post_entry_updated, self, i, old_item
-    end
-  end
-
-  if opt[:autotag]
-    items.map! do |i|
-      new_title = autotag(i.title)
-      if new_title == i.title
-        logger.count(:skipped, level: :debug, message: '%count unchaged %items')
-        # logger.debug('Autotag:', 'No changes')
-      else
-        logger.count(:added_tags)
-        logger.write(items.count == 1 ? :info : :debug, 'Tagged:', new_title)
-        old_item = i.clone
-        i.title = new_title
-        Hooks.trigger :post_entry_updated, self, i, old_item
-      end
-    end
-  end
-
-  if opt[:tag]
-    tag = opt[:tag]
-    items.map! do |i|
-      old_item = i.clone
-      i.tag(tag, date: false, remove: opt[:remove], single: single)
-      i.expand_date_tags(Doing.setting('date_tags'))
-      Hooks.trigger :post_entry_updated, self, i, old_item
-    end
-  end
-
-  if opt[:archive] || opt[:move]
-    section = opt[:archive] ? 'Archive' : guess_section(opt[:move])
-    items.map! do |i|
-      old_item = i.clone
-      i.move_to(section, label: true)
-      Hooks.trigger :post_entry_updated, self, i, old_item
-    end
-  end
-
-  write(@doing_file)
-
-  if opt[:editor]
-    sleep 2 # This seems to be necessary between running fzf
-            # and forking the editor, otherwise vim gets all
-            # screwy and I can't figure out why
-    edit_items(items) # hooked
-
-    write(@doing_file)
-  end
-
-  return unless opt[:output]
-
-  items.each { |i| i.title = "#{i.title} @section(#{i.section})" }
-
-  export_items = Items.new
-  export_items.concat(items)
-  export_items.add_section(Section.new('Export'), log: false)
-  options = { section: 'All' }
-
-  if opt[:output] =~ /doing/
-    options[:output] = 'template'
-    options[:template] = '- %date | %title%note'
-  else
-    options[:output] = opt[:output]
-    options[:template] = opt[:template] || nil
-  end
-
-  output = list_section(options, items: export_items) # hooked
-
-  if opt[:save_to]
-    file = File.expand_path(opt[:save_to])
-    if File.exist?(file)
-      # Create a backup copy for the undo command
-      FileUtils.cp(file, "#{file}~")
-    end
-
-    File.open(file, 'w+') do |f|
-      f.puts output
-    end
-
-    logger.warn('File written:', file)
-  else
-    Doing::Pager.page output
-  end
-end
-
+
@@ -2801,119 +2153,7 @@

-

- - - - -
-
-
-
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-
-
# File 'lib/doing/wwid/modify.rb', line 18
-
-def add_item(title, section = nil, opt)
-  opt ||= {}
-  section ||= Doing.setting('current_section')
-  @content.add_section(section, log: false)
-  opt[:back] ||= opt[:date] ? opt[:date] : Time.now
-  opt[:date] ||= Time.now
-  note = Note.new
-  opt[:timed] ||= false
-
-  note.add(opt[:note]) if opt[:note]
-
-  title = [title.strip.cap_first]
-  title = title.join(' ')
-
-  if Doing.auto_tag
-    title = autotag(title)
-    title.add_tags!(Doing.setting('default_tags')) if Doing.setting('default_tags').good?
-  end
-
-  title.compress!
-  entry = Item.new(opt[:back], title.strip, section)
-
-  if opt[:done] && entry.should_finish?
-    if entry.should_time?
-      finish = opt[:done].is_a?(String) ? opt[:done].chronify(guess: :end, context: :today) : opt[:done]
-      entry.tag('done', value: finish)
-    else
-      entry.tag('done')
-    end
-  end
-
-  entry.note = note
-
-  if opt[:timed]
-    last_item = last_entry({ section: section })
-    if last_item.tags?(['done'], :not)
-      finish_date = verify_duration(last_item.date, opt[:back], title: last_item.title)
-      last_item.tag('done', value: finish_date.strftime('%F %R'))
-    end
-  end
-
-  Hooks.trigger :pre_entry_add, self, entry
-
-  @content.push(entry)
-  # logger.count(:added, level: :debug)
-  logger.info('New entry:', %(added "#{entry.date.relative_date}: #{entry.title}" to #{section}))
-
-  Hooks.trigger :post_entry_added, self, entry
-  entry
-end
-
+
@@ -2947,61 +2187,7 @@

-

- - - - -
-
-
-
-103
-104
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-
-
# File 'lib/doing/wwid/editor.rb', line 103
-
-def add_with_editor(**options)
-  raise MissingEditor, 'No EDITOR variable defined in environment' if Util.default_editor.nil?
-
-  input = options[:date].strftime('%F %R | ')
-  input += options[:title]
-  input += "\n#{options[:note]}" if options[:note]
-  input = fork_editor(input).strip
-
-  d, title, note = format_input(input)
-  raise EmptyInput, 'No content' if title.empty?
-
-  if options[:ask]
-    ask_note = Doing::Prompt.read_lines(prompt: 'Add a note')
-    note.add(ask_note) unless ask_note.empty?
-  end
-
-  date = d.nil? ? options[:date] : d
-  finish = options[:finish_last] || false
-  add_item(title.cap_first, options[:section], { note: note, back: date, timed: finish })
-  write(@doing_file)
-end
-
+
@@ -3109,59 +2295,7 @@

-

- - - - -
-
-
-
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-
-
# File 'lib/doing/wwid/tags.rb', line 18
-
-def all_tags(items, opt: {}, counts: false)
-  if counts
-    all_tags = {}
-    items.each do |item|
-      item.tags.each do |tag|
-        if all_tags.key?(tag.downcase)
-          all_tags[tag.downcase] += 1
-        else
-          all_tags[tag.downcase] = 1
-        end
-      end
-    end
-
-    all_tags.sort_by { |_, count| count }
-  else
-    all_tags = []
-    items.each { |item| all_tags.concat(item.tags.map(&:downcase)).uniq! }
-    all_tags.sort
-  end
-end
-
+
@@ -3220,67 +2354,7 @@

-

- - - - -
-
-
-
-417
-418
-419
-420
-421
-422
-423
-424
-425
-426
-427
-428
-429
-430
-431
-432
-433
-434
-435
-436
-437
-438
-439
-440
-
-
# File 'lib/doing/wwid/modify.rb', line 417
-
-def archive(section = Doing.setting('current_section'), options)
-  options ||= {}
-  count       = options[:keep] || 0
-  destination = options[:destination] || 'Archive'
-  tags        = options[:tags] || []
-  bool        = options[:bool] || :and
-
-  section = section[0] if section.is_a?(Array) && section.count == 1
-  section = choose_section if section.nil? || section.empty? || section.is_a?(String) && section =~ /choose/i
-  archive_all = section =~ /^all$/i # && !(tags.nil? || tags.empty?)
-  section = guess_section(section) unless archive_all
-
-  @content.add_section(destination, log: true)
-  # add_section(Section.new('Archive')) if destination =~ /^archive$/i && !@content.section?('Archive')
-
-  destination = guess_section(destination)
-
-  if @content.section?(destination) && (@content.section?(section) || archive_all)
-    do_archive(section, destination, { count: count, tags: tags, bool: bool, search: options[:search], label: options[:label], before: options[:before], after: options[:after], from: options[:from] })
-    write(doing_file)
-  else
-    raise InvalidArgument, 'Either source or destination does not exist'
-  end
-end
-
+
@@ -3323,217 +2397,7 @@

-

- - - - -
-
-
-
-449
-450
-451
-452
-453
-454
-455
-456
-457
-458
-459
-460
-461
-462
-463
-464
-465
-466
-467
-468
-469
-470
-471
-472
-473
-474
-475
-476
-477
-478
-479
-480
-481
-482
-483
-484
-485
-486
-487
-488
-489
-490
-491
-492
-493
-494
-495
-496
-497
-498
-499
-500
-501
-502
-503
-504
-505
-506
-507
-508
-509
-510
-511
-512
-513
-514
-515
-516
-517
-518
-519
-520
-521
-522
-523
-524
-525
-526
-527
-528
-529
-530
-531
-532
-533
-534
-535
-536
-537
-538
-539
-540
-541
-542
-543
-544
-545
-546
-547
-
-
# File 'lib/doing/wwid/modify.rb', line 449
-
-def autotag(string)
-  return unless string
-  return string unless Doing.auto_tag
-
-  original = string.dup
-  text = string.dup
-
-  current_tags = text.scan(/@\w+/).map { |t| t.sub(/^@/, '') }
-  tagged = {
-    whitelisted: [],
-    synonyms: [],
-    transformed: [],
-    replaced: []
-  }
-
-  Doing.setting('autotag.whitelist').each do |tag|
-    next if text =~ /@#{tag}\b/i
-
-    text.sub!(/(?<= |\A)(#{tag.strip})(?= |\Z)/i) do |m|
-      m.downcase! unless tag =~ /[A-Z]/
-      tagged[:whitelisted].push(m)
-      "@#{m}"
-    end
-  end
-
-  Doing.setting('autotag.synonyms').each do |tag, v|
-    v.each do |word|
-      word = word.wildcard_to_rx
-      next unless text =~ /\b#{word}\b/i
-
-      unless current_tags.include?(tag) || tagged[:whitelisted].include?(tag)
-        tagged[:synonyms].push(tag)
-        tagged[:synonyms] = tagged[:synonyms].uniq
-      end
-    end
-  end
-
-  if Doing.setting('autotag.transform')
-    Doing.setting('autotag.transform').each do |tag|
-      next unless tag =~ /\S+:\S+/
-
-      if tag =~ /::/
-        rx, r = tag.split(/::/)
-      else
-        rx, r = tag.split(/:/)
-      end
-
-      flag_rx = %r{/([r]+)$}
-      if r =~ flag_rx
-        flags = r.match(flag_rx)[1].split(//)
-        r.sub!(flag_rx, '')
-      end
-      r.gsub!(/\$/, '\\')
-      rx.sub!(/^@?/, '@')
-      regex = Regexp.new("(?<= |\\A)#{rx}(?= |\\Z)")
-
-      text.sub!(regex) do
-        m = Regexp.last_match
-        new_tag = r
-
-        m.to_a.slice(1, m.length - 1).each_with_index do |v, idx|
-          next if v.nil?
-
-          new_tag.gsub!("\\#{idx + 1}", v)
-        end
-        # Replace original tag if /r
-        if flags&.include?('r')
-          tagged[:replaced].concat(new_tag.split(/ /).map { |t| t.sub(/^@/, '') })
-          new_tag.split(/ /).map { |t| t.sub(/^@?/, '@') }.join(' ')
-        else
-          tagged[:transformed].concat(new_tag.split(/ /).map { |t| t.sub(/^@/, '') })
-          tagged[:transformed] = tagged[:transformed].uniq
-          m[0]
-        end
-      end
-    end
-  end
-
-  logger.debug('Autotag:', "whitelisted tags: #{tagged[:whitelisted].log_tags}") unless tagged[:whitelisted].empty?
-  logger.debug('Autotag:', "synonyms: #{tagged[:synonyms].log_tags}") unless tagged[:synonyms].empty?
-  logger.debug('Autotag:', "transforms: #{tagged[:transformed].log_tags}") unless tagged[:transformed].empty?
-  logger.debug('Autotag:', "transform replaced: #{tagged[:replaced].log_tags}") unless tagged[:replaced].empty?
-
-  tail_tags = tagged[:synonyms].concat(tagged[:transformed])
-  tail_tags.sort!
-  tail_tags.uniq!
-
-  text.add_tags!(tail_tags) unless tail_tags.empty?
-
-  if text == original
-    logger.debug('Autotag:', "no change to \"#{text.strip}\"")
-  else
-    new_tags = tagged[:whitelisted].concat(tail_tags).concat(tagged[:replaced])
-    logger.debug('Autotag:', "added #{new_tags.log_tags} to \"#{text.strip}\"")
-    logger.count(:autotag, level: :info, count: 1, message: 'autotag updated %count %items')
-  end
-
-  text.dedup_tags
-end
-
+
@@ -3574,25 +2438,7 @@

-

- - - - -
-
-
-
-97
-98
-99
-
-
# File 'lib/doing/wwid/wwidutil.rb', line 97
-
-def changes
-  @content.diff(@initial_content)
-end
-
+
@@ -3631,31 +2477,7 @@

-

- - - - -
-
-
-
-306
-307
-308
-309
-310
-311
-
-
# File 'lib/doing/wwid/interactive.rb', line 306
-
-def choose_section(include_all: false)
-  options = @content.section_titles.sort
-  options.unshift('All') if include_all
-  choice = Prompt.choose_from(options, prompt: 'Choose a section > ', fzf_args: ['--height=60%'])
-  choice ? choice.strip : choice
-end
-
+
@@ -3694,31 +2516,7 @@

-

- - - - -
-
-
-
-335
-336
-337
-338
-339
-340
-
-
# File 'lib/doing/wwid/interactive.rb', line 335
-
-def 
-  options = @content.section_titles.sort
-  options.concat(@content.all_tags.sort.map { |t| "@#{t}" })
-  choice = Prompt.choose_from(options, prompt: 'Choose a section or tag > ', fzf_args: ['--height=60%'])
-  choice ? choice.strip : choice
-end
-
+
@@ -3757,41 +2555,7 @@

-

- - - - -
-
-
-
-318
-319
-320
-321
-322
-323
-324
-325
-326
-327
-328
-
-
# File 'lib/doing/wwid/interactive.rb', line 318
-
-def choose_tag(section = 'All', items: nil, include_all: false)
-  items ||= @content.in_section(section)
-  tags = all_tags(items, counts: true).map { |t, c| "@#{t} (#{c})" }
-  tags.unshift('No tag filter') if include_all
-  choice = Prompt.choose_from(tags,
-                              sorted: false,
-                              multiple: true,
-                              prompt: 'Choose tag(s) > ',
-                              fzf_args: ['--height=60%'])
-  choice ? choice.split(/\n/).map { |t| t.strip.sub(/ \(.*?\)$/, '') }.join(' ') : choice
-end
-
+
@@ -3830,27 +2594,7 @@

-

- - - - -
-
-
-
-347
-348
-349
-350
-
-
# File 'lib/doing/wwid/interactive.rb', line 347
-
-def choose_view
-  choice = Prompt.choose_from(views.sort, prompt: 'Choose a view > ', fzf_args: ['--height=60%'])
-  choice ? choice.strip : choice
-end
-
+
@@ -3895,45 +2639,7 @@

-

- - - - -
-
-
-
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-
-
# File 'lib/doing/wwid/wwidutil.rb', line 56
-
-def configure(filename = nil)
-  logger.benchmark(:configure, :start)
-
-  if filename
-    Doing.config_with(filename, { ignore_local: true })
-  elsif ENV['DOING_CONFIG']
-    Doing.config_with(ENV['DOING_CONFIG'], { ignore_local: true })
-  end
-
-  logger.benchmark(:configure, :finish)
-
-  Doing.set('backup_dir', ENV['DOING_BACKUP_DIR']) if ENV['DOING_BACKUP_DIR']
-end
-
+
@@ -3955,39 +2661,7 @@

-
- - - - -
-
-
-
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-
-
# File 'lib/doing/wwid/filetools.rb', line 75
-
-def create(filename = nil)
-  filename = @doing_file if filename.nil?
-  return if File.exist?(filename) && File.stat(filename).size.positive?
-
-  FileUtils.mkdir_p(File.dirname(filename)) unless File.directory?(File.dirname(filename))
-
-  File.open(filename, 'w+') do |f|
-    f.puts "#{Doing.setting('current_section')}:"
-  end
-end
-
+

@@ -4048,43 +2722,7 @@

-

- - - - -
-
-
-
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-
-
# File 'lib/doing/wwid/wwidutil.rb', line 14
-
-def dedup(items, no_overlap: false)
-  items.delete_if do |item|
-    duped = false
-    @content.each do |comp|
-      duped = no_overlap ? item.overlapping_time?(comp) : item.same_time?(comp)
-      break if duped
-    end
-    logger.count(:skipped, level: :debug, message: '%count overlapping %items') if duped
-    # logger.log_now(:debug, 'Skipped:', "overlapping entry: #{item.title}") if duped
-    duped
-  end
-end
-
+
@@ -4142,39 +2780,7 @@

-

- - - - -
-
-
-
-399
-400
-401
-402
-403
-404
-405
-406
-407
-408
-
-
# File 'lib/doing/wwid/modify.rb', line 399
-
-def delete_items(items, force: false)
-  items.slice(0, 5).each { |i| puts i.to_pretty } unless force
-  puts softpurple("+ #{items.size - 5} additional #{'item'.to_p(items.size - 5)}") if items.size > 5 && !force
-
-  res = force ? true : Prompt.yn("Delete #{items.size} #{'item'.to_p(items.size)}?", default_response: 'y')
-  return unless res
-
-  items.each { |i| Hooks.trigger :post_entry_removed, self, @content.delete_item(i, single: items.count == 1) }
-  # write(@doing_file)
-end
-
+
@@ -4186,117 +2792,7 @@

-

- - - - -
-
-
-
-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
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-
-
# File 'lib/doing/wwid/editor.rb', line 125
-
-def edit_items(items)
-  items.sort_by! { |i| i.date }
-  editable_items = []
-
-  items.each do |i|
-    editable = "#{i.date.strftime('%F %R')} | #{i.title}"
-    old_note = i.note ? i.note.strip_lines.join("\n") : nil
-    editable += "\n#{old_note}" unless old_note.nil?
-    editable_items << editable
-  end
-  divider = "-----------"
-  notice =<<~EONOTICE
-
-  # - You may delete entries, but leave all divider lines (---) in place.
-  # - Start and @done dates replaced with a time string (yesterday 3pm) will
-  #   be parsed automatically. Do not delete the pipe (|) between start date
-  #   and entry title.
-  EONOTICE
-  input =  "#{editable_items.map(&:strip).join("\n#{divider}\n")}\n"
-
-  new_items = fork_editor(input, message: notice).split(/^#{divider}/).map(&:strip)
-
-  new_items.each_with_index do |new_item, i|
-    input_lines = new_item.split(/[\n\r]+/).delete_if(&:ignore?)
-    first_line = input_lines[0]&.strip
-
-    if first_line.nil? || first_line =~ /^#{divider.strip}$/ || first_line.strip.empty?
-      deleted = @content.delete_item(items[i], single: new_items.count == 1)
-      Hooks.trigger :post_entry_removed, self, deleted
-      Doing.logger.info('Deleted:', deleted.title)
-    else
-      date, title, note = format_input(new_item)
-
-      note.map!(&:strip)
-      note.delete_if(&:ignore?)
-      item = items[i]
-      old_item = item.clone
-      item.date = date || items[i].date
-      item.title = title
-      item.note = note
-      if (item.equal?(old_item))
-        Doing.logger.count(:skipped, level: :debug)
-      else
-        Doing.logger.count(:updated)
-        Hooks.trigger :post_entry_updated, self, item, old_item
-      end
-    end
-  end
-end
-
+

@@ -4352,85 +2848,7 @@

-

- - - - -
-
-
-
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-
-
# File 'lib/doing/wwid/editor.rb', line 180
-
-def edit_last(section: 'All', options: {})
-  options[:section] = guess_section(section)
-
-  item = last_entry(options)
-
-  if item.nil?
-    logger.debug('Skipped:', 'No entries found')
-    return
-  end
-
-  old_item = item.clone
-  content = ["#{item.date.strftime('%F %R')} | #{item.title.dup}"]
-  content << item.note.strip_lines.join("\n") unless item.note.empty?
-  new_item = fork_editor(content.join("\n"))
-  raise UserCancelled, 'No change' if new_item.strip == content.join("\n").strip
-
-  date, title, note = format_input(new_item)
-  date ||= item.date
-
-  if title.nil? || title.empty?
-    logger.debug('Skipped:', 'No content provided')
-  elsif title == item.title && note.equal?(item.note) && date.equal?(item.date)
-    logger.debug('Skipped:', 'No change in content')
-  else
-    item.date = date unless date.nil?
-    item.title = title
-    item.note.add(note, replace: true)
-    logger.info('Edited:', item.title)
-    Hooks.trigger :post_entry_updated, self, item, old_item
-
-    write(@doing_file)
-  end
-end
-
+
@@ -4702,129 +3120,7 @@

-

- - - - -
-
-
-
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-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
-
-
# File 'lib/doing/wwid/filter.rb', line 61
-
-def filter_items(items = Items.new, opt: {})
-  logger.benchmark(:filter_items, :start)
-  time_rx = /^(\d{1,2}+(:\d{1,2}+)?( *(am|pm))?|midnight|noon)$/i
-
-  if items.nil? || items.empty?
-    section = !opt[:section] || opt[:section].empty? ? 'All' : guess_section(opt[:section])
-    if section.is_a?(Array)
-      section.each do |s|
-        s = s[0] if s.is_a?(Array)
-        items.concat(s =~ /^all$/i ? @content.clone : @content.in_section(s))
-      end
-    else
-      items = section =~ /^all$/i ? @content.clone : @content.in_section(section)
-    end
-  end
-
-  unless opt[:time_filter]
-    opt[:time_filter] = [nil, nil]
-    if opt[:from] && !opt[:date_filter]
-      if opt[:from][0].is_a?(String) && opt[:from][0] =~ time_rx
-        opt[:time_filter] = opt[:from]
-      elsif opt[:from][0].is_a?(Time)
-        opt[:date_filter] = opt[:from]
-      end
-    end
-  end
-
-  if opt[:before].is_a?(String) && opt[:before] =~ time_rx
-    opt[:time_filter][1] = opt[:before]
-    opt[:before] = nil
-  end
-
-  if opt[:after].is_a?(String) && opt[:after] =~ time_rx
-    opt[:time_filter][0] = opt[:after]
-    opt[:after] = nil
-  end
-
-  items.sort_by! { |item| [item.date, item.title.downcase] }.reverse
-
-  filtered_items = items.select { |item| item.keep_item?(opt) }
-
-  count = opt[:count].to_i&.positive? ? opt[:count].to_i : filtered_items.count
-
-  output = Items.new
-
-  if opt[:age] && opt[:age].normalize_age == :oldest
-    output.concat(filtered_items.slice(0, count).reverse)
-  else
-    output.concat(filtered_items.reverse.slice(0, count))
-  end
-
-  logger.benchmark(:filter_items, :finish)
-
-  output
-end
-
+
@@ -4880,103 +3176,7 @@

-

- - - - -
-
-
-
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-
-
# File 'lib/doing/wwid/editor.rb', line 10
-
-def fork_editor(input = '', message: :default)
-  # raise NonInteractive, 'Non-interactive terminal' unless $stdout.isatty || ENV['DOING_EDITOR_TEST']
-
-  raise MissingEditor, 'No EDITOR variable defined in environment' if Util.default_editor.nil?
-
-  tmpfile = Tempfile.new(['doing_temp', '.doing'])
-
-  File.open(tmpfile.path, 'w+') do |f|
-    f.puts input
-    unless message.nil?
-      f.puts message == :default ? '# First line is the entry title, lines after are added as a note' : message
-    end
-  end
-
-  pid = Process.fork { system("#{Util.editor_with_args} #{tmpfile.path}") }
-
-  trap('INT') do
-    begin
-      Process.kill(9, pid)
-    rescue StandardError
-      Errno::ESRCH
-    end
-    tmpfile.unlink
-    tmpfile.close!
-    exit 0
-  end
-
-  Process.wait(pid)
-
-  begin
-    if $?.exitstatus == 0
-      input = IO.read(tmpfile.path)
-    else
-      exit_now! 'Cancelled'
-    end
-  ensure
-    tmpfile.close
-    tmpfile.unlink
-  end
-
-  input.split(/\n/).delete_if(&:ignore?).join("\n")
-end
-
+
@@ -5047,103 +3247,7 @@

-

- - - - -
-
-
-
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-100
-101
-
-
# File 'lib/doing/wwid/editor.rb', line 60
-
-def format_input(input)
-  raise EmptyInput, 'No content in entry' if input.nil? || input.strip.empty?
-
-  input_lines = input.split(/[\n\r]+/).delete_if(&:ignore?)
-  title = input_lines[0]&.strip
-  raise EmptyInput, 'No content in first line' if title.nil? || title.strip.empty?
-
-  date = nil
-  iso_rx = /\d{4}-\d\d-\d\d \d\d:\d\d/
-  date_rx = /^(?:\s*- )?(?<date>.*?) \| (?=\S)/
-
-  raise EmptyInput, 'No content' if title.sub(/^.*?\| */, '').strip.empty?
-
-  title.expand_date_tags(Doing.setting('date_tags'))
-
-  if title =~ date_rx
-    m = title.match(date_rx)
-    d = m['date']
-    date = if d =~ iso_rx
-             Time.parse(d)
-           else
-             d.chronify(guess: :begin)
-           end
-    title.sub!(date_rx, '').strip!
-  end
-
-  note = Note.new
-  note.add(input_lines[1..-1]) if input_lines.length > 1
-  # If title line ends in a parenthetical, use that as the note
-  if note.empty? && title =~ /\s+\(.*?\)$/
-    title.sub!(/\s+\((?<note>.*?)\)$/) do
-      m = Regexp.last_match
-      note.add(m['note'])
-      ''
-    end
-  end
-
-  note.strip_lines!
-  note.compress
-
-  [date, title, note]
-end
-
+
@@ -5155,43 +3259,7 @@

-

- - - - -
-
-
-
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-
-
# File 'lib/doing/wwid/filter.rb', line 27
-
-def fuzzy_filter_args(query, case_type)
-  fzf_args = ['--multi', %(--filter="#{query.sub(/^'?/, "'")}"), '--no-sort', '-d "\|"', '--nth=1']
-  fzf_args << case case_type.normalize_case
-              when :smart
-                query =~ /[A-Z]/ ? '+i' : '-i'
-              when :sensitive
-                '+i'
-              when :ignore
-                '-i'
-              end
-  fzf_args
-end
-
+
@@ -5283,41 +3351,7 @@

-

- - - - -
-
-
-
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-
-
# File 'lib/doing/wwid/filter.rb', line 15
-
-def fuzzy_filter_items(items, query, case_type: :smart)
-  scannable = items.map.with_index { |item, idx| "#{item.title} #{item.note.join(' ')}".gsub(/[|*?!]/, '') + "|#{idx}" }.join("\n")
-
-  res = `echo #{Shellwords.escape(scannable)}|#{Prompt.fzf} #{fuzzy_filter_args(query, case_type).join(' ')}`
-  selected = Items.new
-  res.split(/\n/).each do |item|
-    idx = item.match(/\|(\d+)$/)[1].to_i
-    selected.push(items[idx])
-  end
-  selected
-end
-
+
@@ -5373,47 +3407,7 @@

-

- - - - -
-
-
-
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-
-
# File 'lib/doing/wwid/wwidutil.rb', line 75
-
-def get_diff(filename = nil)
-  configure if Doing.settings.nil?
-
-  filename ||= Doing.setting('doing_file')
-  init_doing_file(filename)
-  current_content = @content.clone
-  backup_file = Util::Backup.last_backup(filename, count: 1)
-  raise DoingRuntimeError, 'No undo history to diff' if backup_file.nil?
-
-  backup = WWID.new
-  backup.config = Doing.settings
-  backup.init_doing_file(backup_file)
-  current_content.diff(backup.content)
-end
-
+
@@ -5510,41 +3504,7 @@

-

- - - - -
-
-
-
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-
-
# File 'lib/doing/wwid/timers.rb', line 154
-
-def get_interval(item, formatted: true, record: true)
-  if item.interval
-    seconds = item.interval
-    record_tag_times(item, seconds) if record
-    return seconds.positive? ? seconds : false unless formatted
-
-    return seconds.positive? ? seconds.time_string(format: :clock) : false
-  end
-
-  false
-end
-
+
@@ -5585,25 +3545,7 @@

-

- - - - -
-
-
-
-103
-104
-105
-
-
# File 'lib/doing/wwid/wwid.rb', line 103
-
-def get_view(title, fallback: nil)
-  Doing.setting(['views', title], fallback)
-end
-
+
@@ -5661,113 +3603,7 @@

-

- - - - -
-
-
-
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-
-
# File 'lib/doing/wwid/guess.rb', line 11
-
-def guess_section(frag, guessed: false, suggest: false)
-  if frag.is_a?(Array) && frag.count == 1
-    frag = frag[0]
-  end
-
-  frag = frag.split(/ *, */).map(&:strip) if frag.is_a?(String) && frag =~ /,/
-
-  return frag.map { |s| guess_section(s, guessed: guessed, suggest: suggest) } if frag.is_a?(Array)
-
-  return 'All' if frag.empty? || frag.nil? || frag =~ /^all$/i
-
-  frag ||= Doing.setting('current_section')
-
-  return frag.cap_first if @content.section?(frag)
-
-  found = @content.guess_section(frag, distance: 2)
-
-  section = found ? found.title : nil
-
-  if section && suggest
-    Doing.logger.debug('Match:', %(Assuming "#{section}" from "#{frag}"))
-    return section
-  end
-
-  unless section || guessed
-    alt = guess_view(frag, guessed: true, suggest: true)
-    if alt
-      prompt = Color.template("{bw}Did you mean `{xy}doing {by}view {xy}#{alt}`{bw}?{x}")
-      meant_view = Prompt.yn(prompt, default_response: 'n')
-
-      msg = format('%<y>srun with `%<w>sdoing view %<alt>s%<y>s`', w: boldwhite, y: yellow, alt: alt)
-      raise Errors::WrongCommand.new(msg, topic: 'Try again:') if meant_view
-
-    end
-
-    res = Prompt.yn("#{boldwhite}Section #{frag.yellow}#{boldwhite} not found, create it", default_response: 'n')
-
-    if res
-      @content.add_section(frag.cap_first, log: true)
-      write(@doing_file)
-      return frag.cap_first
-    end
-
-    raise Errors::InvalidSection.new("unknown section #{frag.bold.white}", topic: 'Missing:')
-  end
-  section ? section.cap_first : nil
-end
-
+
@@ -5825,79 +3661,7 @@

-

- - - - -
-
-
-
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-
-
# File 'lib/doing/wwid/guess.rb', line 65
-
-def guess_view(frag, guessed: false, suggest: false)
-  views.each { |view| return view if frag.downcase == view.downcase }
-  view = nil
-  re = frag.to_rx(distance: 2, case_type: :ignore)
-  views.each do |v|
-    next unless v =~ /#{re}/i
-
-    logger.debug('Match:', %(Assuming "#{v}" from "#{frag}"))
-    view = v
-    break
-  end
-  unless view || guessed
-    alt = guess_section(frag, guessed: true, suggest: true)
-
-    raise Errors::InvalidView.new(%(unknown view #{frag.bold.white}), topic: 'Missing:') unless alt
-
-    prompt = Color.template("{bw}Did you mean `{xy}doing {by}show {xy}#{alt}`{bw}?{x}")
-    meant_view = Prompt.yn(prompt, default_response: 'n')
-
-    if meant_view
-      msg = format('%<y>srun with `%<w>sdoing show %<alt>s%<y>s`', w: boldwhite, y: yellow, alt: alt)
-      raise Errors::WrongCommand.new(msg, topic: 'Try again:')
-
-    end
-
-    raise Errors::InvalidView.new(%(unknown view #{alt.bold.white}), topic: 'Missing:')
-
-  end
-  view
-end
-
+
@@ -5953,49 +3717,7 @@

-

- - - - -
-
-
-
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-
-
# File 'lib/doing/wwid/wwidutil.rb', line 33
-
-def import(paths, opt)
-  opt ||= {}
-  Plugins.plugins[:import].each do |_, options|
-    next unless opt[:type] =~ /^(#{options[:trigger].normalize_trigger})$/i
-
-    if paths.count.positive?
-      paths.each do |path|
-        options[:class].import(self, path, options: opt)
-      end
-    else
-      options[:class].import(self, nil, options: opt)
-    end
-    break
-  end
-end
-
+
@@ -6038,141 +3760,7 @@

-

- - - - -
-
-
-
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-
-
# File 'lib/doing/wwid/filetools.rb', line 10
-
-def init_doing_file(path = nil)
-  @doing_file =  File.expand_path(Doing.setting('doing_file'))
-
-  if path.nil?
-    create(@doing_file) unless File.exist?(@doing_file)
-    input = IO.read(@doing_file)
-    input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
-    logger.debug('Read:', "read file #{@doing_file}")
-  elsif File.exist?(File.expand_path(path)) && File.file?(File.expand_path(path)) && File.stat(File.expand_path(path)).size.positive?
-    @doing_file = File.expand_path(path)
-    input = IO.read(File.expand_path(path))
-    input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
-    logger.debug('Read:', "read file #{File.expand_path(path)}")
-  elsif path.length < 256
-    @doing_file = File.expand_path(path)
-    create(path)
-    input = IO.read(File.expand_path(path))
-    input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
-    logger.debug('Read:', "read file #{File.expand_path(path)}")
-  end
-
-  @other_content_top = []
-  @other_content_bottom = []
-
-  section = nil
-  lines = input.split(/[\n\r]/)
-
-  lines.each do |line|
-    next if line =~ /^\s*$/
-
-    if line =~ /^(\S[\S ]+):\s*(@[\w\-_.]+\s*)*$/
-      section = Regexp.last_match(1)
-      @content.add_section(Section.new(section, original: line), log: false)
-    elsif line =~ /^\s*- (\d{4}-\d\d-\d\d \d\d:\d\d) \| (.*?)(?: +<([a-z0-9]{32})>)? *$/
-      if section.nil?
-        section = 'Uncategorized'
-        @content.add_section(Section.new(section, original: 'Uncategorized:'), log: false)
-      end
-
-      date = Regexp.last_match(1).strip
-      title = Regexp.last_match(2).strip
-      id = Regexp.last_match(3) || nil
-      item = Item.new(date, title, section, [], id)
-      @content.push(item)
-    elsif @content.count.zero?
-      # if content[section].items.length - 1 == current
-      @other_content_top.push(line)
-    elsif line =~ /^\S/
-      @other_content_bottom.push(line)
-    else
-      prev_item = @content.last
-      prev_item.note = Note.new unless prev_item.note
-
-      prev_item.note.add(line)
-      # end
-    end
-  end
-
-  Hooks.trigger :post_read, self
-  @initial_content = @content.clone
-end
-
+
@@ -6228,83 +3816,7 @@

-

- - - - -
-
-
-
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-
-
# File 'lib/doing/wwid/interactive.rb', line 12
-
-def interactive(opt)
-  opt ||= {}
-  opt[:section] = opt[:section] ? guess_section(opt[:section]) : 'All'
-
-  search = nil
-
-  if opt[:search]
-    search = opt[:search]
-    search.sub!(/^'?/, "'") if opt[:exact]
-    opt[:search] = search
-  end
-
-  # opt[:query] = opt[:search] if opt[:search] && !opt[:query]
-  opt[:query] = "!#{opt[:query]}" if opt[:query] && opt[:not]
-  opt[:multiple] = true
-  opt[:show_if_single] = true
-  filter_options = %i[after before case date_filter from fuzzy not search section val].each_with_object({}) {
-    |k, hsh| hsh[k] = opt[k]
-  }
-  items = filter_items(Items.new, opt: filter_options)
-
-  menu_options = %i[search query exact multiple show_if_single menu sort case].each_with_object({}) {
-    |k, hsh| hsh[k] = opt[k]
-  }
-  include_section = (opt[:section].is_a?(Array) && opt[:section][0] =~ /^all$/i) || (opt[:section].is_a?(String) && opt[:section] =~ /^all$/i)
-
-  selection = Prompt.choose_from_items(items, include_section: include_section, **menu_options)
-
-  raise NoResults, 'no items selected' if selection.nil? || selection.empty?
-
-  act_on(selection, opt)
-end
-
+
@@ -6364,103 +3876,7 @@

-

- - - - -
-
-
-
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-
-
# File 'lib/doing/wwid/display.rb', line 258
-
-def last(times: true, section: nil, options: {})
-  section = section[0] if section.is_a?(Array) && section.count == 1
-  section = section.nil? ? 'All' : guess_section(section)
-  cfg = Doing.setting(['templates', options[:config_template]]).deep_merge(Doing.setting('templates.default'), { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
-    'wrap_width' => Doing.setting('wrap_width', 0),
-    'date_format' => Doing.setting('default_date_format'),
-    'order' => Doing.setting('order', :asc),
-    'tags_color' => Doing.setting('tags_color'),
-    'duration' => Doing.setting('duration'),
-    'interval_format' => Doing.setting('interval_format')
-  }, { extend_existing_arrays: true, sort_merged_arrays: true })
-  options[:duration] ||= cfg['duration'] || false
-  options[:interval_format] ||= cfg['interval_format'] || 'text'
-
-  opts = {
-    case: options[:case],
-    config_template: options[:config_template] || 'last',
-    count: 1,
-    delete: options[:delete],
-    duration: options[:duration],
-    format: cfg['date_format'],
-    interval_format: options[:interval_format],
-    not: options[:negate],
-    output: options[:output],
-    section: section,
-    template: options[:template] || cfg['template'],
-    times: times,
-    val: options[:val],
-    wrap_width: cfg['wrap_width']
-  }
-
-  if options[:tag]
-    opts[:tag_filter] = {
-      'tags' => options[:tag],
-      'bool' => options[:tag_bool]
-    }
-  end
-
-  opts[:search] = options[:search] if options[:search]
-
-  list_section(opts)
-end
-
+
@@ -6501,67 +3917,7 @@

-

- - - - -
-
-
-
-325
-326
-327
-328
-329
-330
-331
-332
-333
-334
-335
-336
-337
-338
-339
-340
-341
-342
-343
-344
-345
-346
-347
-348
-
-
# File 'lib/doing/wwid/display.rb', line 325
-
-def last_entry(opt)
-  opt ||= {}
-  opt[:tag_bool] ||= :and
-  opt[:section] ||= Doing.setting('current_section')
-
-  items = filter_items(Items.new, opt: opt)
-
-  logger.debug('Filtered:', "Parameters matched #{items.count} entries")
-
-  if opt[:interactive]
-    last_entry = Prompt.choose_from_items(items, include_section: opt[:section] =~ /^all$/i,
-      menu: true,
-      header: '',
-      prompt: 'Select an entry > ',
-      multiple: false,
-      sort: false,
-      show_if_single: true
-     )
-  else
-    last_entry = items.max_by { |item| item.date }
-  end
-
-  last_entry
-end
-
+
@@ -6618,43 +3974,7 @@

-

- - - - -
-
-
-
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-
-
# File 'lib/doing/wwid/display.rb', line 307
-
-def last_note(section = 'All')
-  section = guess_section(section)
-
-  last_item = last_entry({ section: section })
-
-  raise NoEntryError, 'No entry found' unless last_item
-
-  logger.log_now(:info, 'Edit note:', last_item.title)
-
-  note = last_item.note&.to_s || ''
-  "#{last_item.title}\n# EDIT BELOW THIS LINE ------------\n#{note}"
-end
-
+
@@ -6759,63 +4079,7 @@

-

- - - - -
-
-
-
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-
-
# File 'lib/doing/wwid/display.rb', line 107
-
-def list_date(dates, section, times = nil, output = nil, opt)
-  opt ||= {}
-  opt[:totals] ||= false
-  opt[:sort_tags] ||= false
-  section = guess_section(section)
-  # :date_filter expects an array with start and end date
-  dates = dates.split_date_range if dates.instance_of?(String)
-
-  opt[:section] = section
-  opt[:count] = 0
-  opt[:order] = :asc
-  opt[:date_filter] = dates
-  opt[:times] = times
-  opt[:output] = output
-
-  time_rx = /^(\d{1,2}+(:\d{1,2}+)?( *(am|pm))?|midnight|noon)$/
-  if opt[:from] && opt[:from][0].is_a?(String) && opt[:from][0] =~ time_rx
-    opt[:time_filter] = opt[:from]
-  end
-
-  list_section(opt)
-end
-
+
@@ -6856,193 +4120,7 @@

-

- - - - -
-
-
-
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-
-
# File 'lib/doing/wwid/display.rb', line 10
-
-def list_section(opt, items: Items.new)
-  logger.benchmark(:list_section, :start)
-  opt[:config_template] ||= 'default'
-
-  tpl_cfg = Doing.setting(['templates', opt[:config_template]])
-
-  cfg = if opt[:view_template]
-          Doing.setting(['views', opt[:view_template]]).deep_merge(tpl_cfg, { extend_existing_arrays: true, sort_merged_arrays: true })
-        else
-          tpl_cfg
-        end
-
-  cfg.deep_merge({
-                   'wrap_width' => Doing.setting('wrap_width') || 0,
-                   'date_format' => Doing.setting('default_date_format'),
-                   'order' => Doing.setting('order') || :asc,
-                   'tags_color' => Doing.setting('tags_color'),
-                   'duration' => Doing.setting('duration'),
-                   'interval_format' => Doing.setting('interval_format')
-                 }, { extend_existing_arrays: true, sort_merged_arrays: true })
-
-  opt[:duration] ||= cfg['duration'] || false
-  opt[:interval_format] ||= cfg['interval_format'] || 'text'
-  opt[:count] ||= 0
-  opt[:age] ||= :newest
-  opt[:age] = opt[:age].normalize_age
-  opt[:format] ||= cfg['date_format']
-  opt[:order] ||= cfg['order'] || :asc
-  opt[:tag_order] ||= :asc
-  opt[:tags_color] = cfg['tags_color'] || false if opt[:tags_color].nil?
-  opt[:template] ||= cfg['template']
-  opt[:sort_tags] ||= opt[:tag_sort]
-
-  # opt[:highlight] ||= true
-  title = ''
-  is_single = true
-  if opt[:section].nil?
-    opt[:section] = choose_section
-    title = opt[:section]
-  elsif opt[:section].is_a?(Array)
-    title = opt[:section].join(', ')
-  elsif opt[:section].is_a?(String)
-    title = if opt[:section] =~ /^all$/i
-              if opt[:page_title]
-                opt[:page_title]
-              elsif opt[:tag_filter] && opt[:tag_filter]['bool'].normalize_bool != :not
-                opt[:tag_filter]['tags'].map { |tag| "@#{tag}" }.join(' + ')
-              else
-                'doing'
-              end
-            else
-              guess_section(opt[:section])
-            end
-  end
-
-  items = filter_items(items, opt: opt)
-
-  items.reverse! unless opt[:order].normalize_order == :desc
-
-  if opt[:delete]
-    delete_items(items, force: opt[:force])
-
-    write(@doing_file)
-    return
-  elsif opt[:editor]
-    edit_items(items)
-
-    write(@doing_file)
-    return
-  elsif opt[:interactive]
-    opt[:menu] = !opt[:force]
-    opt[:query] = '' # opt[:search]
-    opt[:multiple] = true
-    selected = Prompt.choose_from_items(items.reverse, include_section: opt[:section] =~ /^all$/i, **opt)
-
-    raise NoResults, 'no items selected' if selected.nil? || selected.empty?
-
-    act_on(selected, opt)
-    return
-  end
-
-  opt[:output] ||= 'template'
-  opt[:wrap_width] ||= Doing.setting('templates.default.wrap_width', 0)
-
-  logger.benchmark(:list_section, :finish)
-  output(items, title, is_single, opt)
-end
-
+
@@ -7070,25 +4148,7 @@

-
- - - - -
-
-
-
-76
-77
-78
-
-
# File 'lib/doing/wwid/wwid.rb', line 76
-
-def logger
-  @logger ||= Doing.logger
-end
-
+

@@ -7163,77 +4223,7 @@

-

- - - - -
-
-
-
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-
-
# File 'lib/doing/wwid/display.rb', line 222
-
-def recent(count = 10, section = nil, opt)
-  opt ||= {}
-  opt[:times] ||= false
-  opt[:totals] ||= false
-  opt[:sort_tags] ||= false
-
-  cfg = Doing.setting('templates.recent').deep_merge(Doing.setting('templates.default'), { extend_existing_arrays: true, sort_merged_arrays: true }).deep_merge({
-    'wrap_width' => Doing.setting('wrap_width') || 0,
-    'date_format' => Doing.setting('default_date_format'),
-    'order' => Doing.setting('order') || :asc,
-    'tags_color' => Doing.setting('tags_color'),
-    'duration' => Doing.setting('duration'),
-    'interval_format' => Doing.setting('interval_format')
-  }, { extend_existing_arrays: true, sort_merged_arrays: true })
-  opt[:duration] ||= cfg['duration'] || false
-  opt[:interval_format] ||= cfg['interval_format'] || 'text'
-
-  section ||= Doing.setting('current_section')
-  section = guess_section(section)
-
-  opt[:section] = section
-  opt[:wrap_width] = cfg['wrap_width']
-  opt[:count] = count
-  opt[:format] = cfg['date_format']
-  opt[:template] = opt[:template] || cfg['template']
-  opt[:order] = :asc
-
-  list_section(opt)
-end
-
+
@@ -7245,41 +4235,7 @@

-

- - - - -
-
-
-
-107
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-
-
# File 'lib/doing/wwid/wwid.rb', line 107
-
-def rename_view_keys(view)
-  options = view.symbolize_keys
-  # options.rename_key(:tags, :tag, keep: true)
-  options.rename_key(:output_format, :output)
-  options.rename_key(:tags_bool, :bool)
-  options.rename_key(:tag_sort, :sort_tags)
-  options.rename_key(:negate, :not)
-  options.rename_key(:order, :sort)
-
-  options
-end
-
+
@@ -7411,95 +4367,7 @@

-

- - - - -
-
-
-
-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
-
-
# File 'lib/doing/wwid/modify.rb', line 100
-
-def repeat_item(item, opt)
-  opt ||= {}
-  old_item = item.clone
-  if item.unfinished? && item.should_finish?
-    if item.should_time?
-      finish_date = verify_duration(item.date, Time.now, title: item.title)
-      item.title.tag!('done', value: finish_date.strftime('%F %R'))
-    else
-      item.title.tag!('done')
-    end
-    Hooks.trigger :post_entry_updated, self, item, old_item
-  end
-
-  # Remove @done tag
-  title = item.title.sub(/\s*@done(\(.*?\))?/, '').chomp
-  section = opt[:in].nil? ? item.section : guess_section(opt[:in])
-  Doing.auto_tag = false
-
-  note = opt[:note] || Note.new
-
-  if opt[:editor]
-    start = opt[:date] ? opt[:date] : Time.now
-    to_edit = "#{start.strftime('%F %R')} | #{title}"
-    to_edit += "\n#{note.strip_lines.join("\n")}" unless note.empty?
-    new_item = fork_editor(to_edit)
-    date, title, note = format_input(new_item)
-
-    opt[:date] = date unless date.nil?
-
-    if title.nil? || title.empty?
-      logger.warn('Skipped:', 'No content provided')
-      return
-    end
-  end
-
-  # @content.update_item(original, item)
-  add_item(title, section, { note: note, back: opt[:date], timed: false })
-end
-
+
@@ -7540,53 +4408,7 @@

-

- - - - -
-
-
-
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-
-
# File 'lib/doing/wwid/modify.rb', line 144
-
-def repeat_last(opt)
-  opt ||= {}
-  opt[:section] ||= 'all'
-  opt[:section] = guess_section(opt[:section])
-  opt[:note] ||= []
-  opt[:tag] ||= []
-  opt[:tag_bool] ||= :and
-
-  last = last_entry(opt)
-  if last.nil?
-    logger.warn('Skipped:', 'No previous entry found')
-    return
-  end
-
-  repeat_item(last, opt)
-  write(@doing_file)
-end
-
+
@@ -7645,43 +4467,7 @@

-

- - - - -
-
-
-
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-
-
# File 'lib/doing/wwid/modify.rb', line 75
-
-def reset_item(item, date: nil, finish_date: nil, resume: false)
-  date ||= Time.now
-  item.date = date
-  if finish_date
-    item.tag('done', remove: true)
-    item.tag('done', value: finish_date.strftime('%F %R'))
-  else
-    item.tag('done', remove: true) if resume
-  end
-  logger.info('Reset:', %(Reset #{resume ? 'and resumed ' : ''} "#{item.title}" in #{item.section}))
-  item
-end
-
+
@@ -7703,135 +4489,7 @@

-
- - - - -
-
-
-
-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
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-
-
# File 'lib/doing/wwid/filetools.rb', line 105
-
-def rotate(opt)
-  opt ||= {}
-  keep = opt[:keep] || 0
-  tags = []
-  tags.concat(opt[:tag].split(/ *, */).map { |t| t.sub(/^@/, '').strip }) if opt[:tag]
-  bool  = opt[:bool] || :and
-
-  sect = opt[:section] !~ /^all$/i ? guess_section(opt[:section]) : 'all'
-
-  section = guess_section(sect)
-
-  section_items = @content.in_section(section)
-  max = section_items.count - keep.to_i
-
-  counter = 0
-  new_content = Items.new
-
-  section_items.each do |item|
-    break if counter >= max
-    if opt[:before]
-      time_string = opt[:before]
-      cutoff = time_string.chronify(guess: :begin)
-    end
-
-    unless ((!tags.empty? && !item.tags?(tags, bool)) || (opt[:search] && !item.search(opt[:search].to_s)) || (opt[:before] && item.date >= cutoff))
-      new_item = @content.delete(item)
-      Hooks.trigger :post_entry_removed, self, item.clone
-      raise DoingRuntimeError, "Error deleting item: #{item}" if new_item.nil?
-
-      new_content.add_section(new_item.section, log: false)
-      new_content.push(new_item)
-      counter += 1
-    end
-  end
-
-  if counter.positive?
-    logger.count(:rotated,
-                 level: :info,
-                 count: counter,
-                 message: "Rotated %count %items")
-  else
-    logger.info('Skipped:', 'No items were rotated')
-  end
-
-  write(@doing_file)
-
-  file = @doing_file.sub(/(\.\w+)$/, "_#{Time.now.strftime('%Y-%m-%d')}\\1")
-  if File.exist?(file)
-    init_doing_file(file)
-    @content.concat(new_content).uniq!
-    logger.warn('File update:', "added entries to existing file: #{file}")
-  else
-    @content = new_content
-    logger.warn('File update:', "created new file: #{file}")
-  end
-
-  write(file, backup: false)
-end
-
+

@@ -7870,25 +4528,7 @@

-

- - - - -
-
-
-
-85
-86
-87
-
-
# File 'lib/doing/wwid/wwid.rb', line 85
-
-def sections
-  @content.section_titles
-end
-
+
@@ -8019,121 +4659,7 @@

-

- - - - -
-
-
-
-341
-342
-343
-344
-345
-346
-347
-348
-349
-350
-351
-352
-353
-354
-355
-356
-357
-358
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-381
-382
-383
-384
-385
-386
-387
-388
-389
-390
-391
-
-
# File 'lib/doing/wwid/modify.rb', line 341
-
-def stop_start(target_tag, opt)
-  opt ||= {}
-  tag = target_tag.dup
-  opt[:section] ||= Doing.setting('current_section')
-  opt[:archive] ||= false
-  opt[:back] ||= Time.now
-  opt[:new_item] ||= false
-  opt[:note] ||= false
-
-  opt[:section] = guess_section(opt[:section])
-
-  tag.sub!(/^@/, '')
-
-  found_items = 0
-
-  @content.each_with_index do |item, i|
-    old_item = i.clone
-    next unless item.section == opt[:section] || opt[:section] =~ /all/i
-
-    next unless item.title =~ /@#{tag}/
-
-    item.title.add_tags!([tag, 'done'], remove: true)
-    item.tag('done', value: opt[:back].strftime('%F %R'))
-
-    found_items += 1
-
-    if opt[:archive] && opt[:section] != 'Archive'
-      item.title = item.title.sub(/(?:@from\(.*?\))?(.*)$/, "\\1 @from(#{item.section})")
-      item.move_to('Archive', label: false, log: false)
-      logger.count(:completed_archived)
-      logger.info('Completed/archived:', item.title)
-    else
-      logger.count(:completed)
-      logger.info('Completed:', item.title)
-    end
-    Hooks.trigger :post_entry_updated, self, item, old_item
-  end
-
-
-  logger.debug('Skipped:', "No active @#{tag} tasks found.") if found_items.zero?
-
-  if opt[:new_item]
-    date, title, note = format_input(opt[:new_item])
-    opt[:back] = date unless date.nil?
-    note.add(opt[:note]) if opt[:note]
-    title.tag!(tag)
-    add_item(title.cap_first, opt[:section], { note: note, back: opt[:back] })
-  end
-
-  write(@doing_file)
-end
-
+
@@ -8145,41 +4671,7 @@

-

- - - - -
-
-
-
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-
-
# File 'lib/doing/wwid/tags.rb', line 39
-
-def tag_groups(items, opt: {})
-  all_items = filter_items(items, opt: opt)
-  tags = all_tags(all_items, opt: {})
-  groups = {}
-  tags.each do |tag|
-    groups[tag] ||= []
-    groups[tag] = filter_items(all_items, opt: { tag: tag, tag_bool: :or })
-  end
-
-  groups
-end
-
+
@@ -8244,327 +4736,7 @@

filter_items for filtering

-
- - - - -
-
-
-
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-230
-231
-232
-233
-234
-235
-236
-237
-238
-239
-240
-241
-242
-243
-244
-245
-246
-247
-248
-249
-250
-251
-252
-253
-254
-255
-256
-257
-258
-259
-260
-261
-262
-263
-264
-265
-266
-267
-268
-269
-270
-271
-272
-273
-274
-275
-276
-277
-278
-279
-280
-281
-282
-283
-284
-285
-286
-287
-288
-289
-290
-291
-292
-293
-294
-295
-296
-297
-298
-299
-300
-301
-302
-303
-304
-305
-306
-307
-308
-309
-310
-311
-312
-313
-314
-315
-316
-317
-318
-319
-320
-321
-322
-323
-324
-
-
# File 'lib/doing/wwid/modify.rb', line 171
-
-def tag_last(opt) # hooked
-  opt ||= {}
-  opt[:count] ||= 1
-  opt[:archive] ||= false
-  opt[:tags] ||= ['done']
-  opt[:sequential] ||= false
-  opt[:date] ||= false
-  opt[:remove] ||= false
-  opt[:update] ||= false
-  opt[:autotag] ||= false
-  opt[:back] ||= false
-  opt[:unfinished] ||= false
-  opt[:section] = opt[:section] ? guess_section(opt[:section]) : 'All'
-
-  items = filter_items(Items.new, opt: opt)
-
-  if opt[:interactive]
-    items = Prompt.choose_from_items(items, include_section: opt[:section] =~ /^all$/i, menu: true,
-                                header: '',
-                                prompt: 'Select entries to tag > ',
-                                multiple: true,
-                                sort: true,
-                                show_if_single: true)
-
-    raise NoResults, 'no items selected' if items.empty?
-
-  end
-
-  raise NoResults, 'no items matched your search' if items.empty?
-
-  if opt[:tags].empty? && !opt[:autotag]
-    completions = opt[:remove] ? all_tags(items) : all_tags(@content)
-    if opt[:remove]
-      puts "#{yellow}Available tags: #{boldwhite}#{completions.map(&:add_at).join(', ')}"
-    else
-      puts "#{yellow}Use tab to complete known tags"
-    end
-    opt[:tags] = Doing::Prompt.read_line(prompt: "Enter tag(s) to #{opt[:remove] ? 'remove' : 'add'}",
-                                         completions: completions,
-                                         default_response: '').to_tags
-    raise UserCancelled, 'No tags provided' if opt[:tags].empty?
-  end
-
-  items.each do |item|
-    old_item = item.clone
-    added = []
-    removed = []
-
-    item.date = opt[:start_date] if opt[:start_date]
-
-    if opt[:autotag]
-      new_title = autotag(item.title) if Doing.auto_tag
-      if new_title == item.title
-        logger.count(:skipped, level: :debug, message: '%count unchaged %items')
-        # logger.debug('Autotag:', 'No changes')
-      else
-        logger.count(:added_tags)
-        logger.write(items.count == 1 ? :info : :debug, 'Tagged:', new_title)
-        item.title = new_title
-      end
-    else
-      if opt[:done_date]
-        done_date = opt[:done_date]
-      elsif opt[:sequential]
-        next_entry = next_item(item)
-
-        done_date = if next_entry.nil?
-                      Time.now
-                    else
-                      next_entry.date - 60
-                    end
-      else
-        done_date = item.calculate_end_date(opt)
-      end
-
-      opt[:tags].each do |tag|
-        if tag == 'done' && !item.should_finish?
-
-          Doing.logger.debug('Skipped:', "Item in never_finish: #{item.title}")
-          logger.count(:skipped, level: :debug)
-          next
-        end
-
-        tag = tag.strip
-
-        if tag =~ /^(\S+)\((.*?)\)$/
-          m = Regexp.last_match
-          tag = m[1]
-          opt[:value] ||= m[2]
-        end
-
-        if tag =~ /^done$/ && opt[:date] && item.should_time?
-          max_elapsed = Doing.setting('interaction.confirm_longer_than', 0)
-          max_elapsed = max_elapsed.chronify_qty if max_elapsed.is_a?(String)
-          elapsed = done_date - item.date
-
-          if max_elapsed.positive? && (elapsed > max_elapsed) && !opt[:took]
-            puts boldwhite(item.title)
-            human = elapsed.time_string(format: :natural)
-            res = Prompt.yn(yellow("Did this actually take #{human}"), default_response: true)
-            unless res
-              new_elapsed = Prompt.enter_text('How long did it take?').chronify_qty
-              raise InvalidTimeExpression, 'Unrecognized time span entry' unless new_elapsed > 0
-
-              opt[:took] = new_elapsed
-              done_date = item.calculate_end_date(opt) if opt[:took]
-            end
-          end
-        end
-
-        if opt[:remove] || opt[:rename] || opt[:value]
-          rename_to = nil
-
-          if opt[:value]
-            rename_to = tag
-          elsif opt[:rename]
-            rename_to = tag
-            tag = opt[:rename]
-          end
-          old_title = item.title.dup
-          force = opt[:value].nil? ? false : true
-          item.title.tag!(tag, remove: opt[:remove], rename_to: rename_to, regex: opt[:regex], value: opt[:value], force: force)
-          if old_title != item.title
-            removed << tag
-            added << rename_to if rename_to
-          else
-            logger.count(:skipped, level: :debug)
-          end
-        else
-          old_title = item.title.dup
-          should_date = opt[:date] && item.should_time?
-          item.title.tag!('done', remove: true) if tag =~ /done/ && (!should_date || opt[:update])
-          item.title.tag!(tag, value: should_date ? done_date.strftime('%F %R') : nil)
-          added << tag if old_title != item.title
-        end
-      end
-    end
-
-    logger.log_change(tags_added: added, tags_removed: removed, item: item, single: items.count == 1)
-
-    item.note.add(opt[:note]) if opt[:note]
-
-    if opt[:archive] && opt[:section] != 'Archive' && (opt[:count]).positive?
-      item.move_to('Archive', label: true)
-    elsif opt[:archive] && opt[:count].zero?
-      logger.warn('Skipped:', 'Archiving is skipped when operating on all entries')
-    end
-
-    item.expand_date_tags(Doing.setting('date_tags'))
-    Hooks.trigger :post_entry_updated, self, item, old_item
-  end
-
-  write(@doing_file)
-end
-
+
@@ -8643,269 +4815,7 @@

-

- - - - -
-
-
-
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-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
-
-
# File 'lib/doing/wwid/timers.rb', line 14
-
-def tag_times(format: :text, sort_by: :time, sort_order: :asc)
-  return '' if @timers.empty?
-
-  @timers.delete('meanwhile')
-
-  max = @timers.keys.sort_by(&:length).reverse[0].length + 1
-
-  total = @timers.delete('All')
-
-  tags_data = @timers.delete_if { |_k, v| v.zero? }
-  sorted_tags_data = if sort_by.normalize_tag_sort == :name
-                       tags_data.sort_by { |k, _v| k }
-                     else
-                       tags_data.sort_by { |_k, v| v }
-                     end
-
-  sorted_tags_data.reverse! if sort_order.normalize_order == :asc
-  case format
-  when :html
-
-    output = <<EOHEAD
-      <table>
-      <caption id="tagtotals">Tag Totals</caption>
-      <colgroup>
-      <col style="text-align:left;"/>
-      <col style="text-align:left;"/>
-      </colgroup>
-      <thead>
-      <tr>
-        <th style="text-align:left;">project</th>
-        <th style="text-align:left;">time</th>
-      </tr>
-      </thead>
-      <tbody>
-EOHEAD
-    sorted_tags_data.reverse.each do |k, v|
-      if v.positive?
-        output += "<tr><td style='text-align:left;'>#{k}</td><td style='text-align:left;'>#{v.time_string(format: :clock)}</td></tr>\n"
-      end
-    end
-    tail = <<EOTAIL
-    <tr>
-      <td style="text-align:left;" colspan="2"></td>
-    </tr>
-    </tbody>
-    <tfoot>
-    <tr>
-      <td style="text-align:left;"><strong>Total</strong></td>
-      <td style="text-align:left;">#{total.time_string(format: :clock)}</td>
-    </tr>
-    </tfoot>
-    </table>
-EOTAIL
-    output + tail
-  when :markdown
-    pad = sorted_tags_data.map { |k, _| k }.group_by(&:size).max.last[0].length
-    pad = 7 if pad < 7
-    output = <<~EOHEADER
-  | #{' ' * (pad - 7)}project | time     |
-  | #{'-' * (pad - 1)}: | :------- |
-    EOHEADER
-    sorted_tags_data.reverse.each do |k, v|
-      if v.positive?
-        output += "| #{' ' * (pad - k.length)}#{k} | #{v.time_string(format: :clock)} |\n"
-      end
-    end
-    tail = '[Tag Totals]'
-    output + tail
-  when :json
-    output = []
-    sorted_tags_data.reverse.each do |k, v|
-      output << {
-        'tag' => k,
-        'seconds' => v,
-        'formatted' => v.time_string(format: :clock)
-      }
-    end
-    output
-  when :human
-    output = []
-    sorted_tags_data.reverse.each do |k, v|
-      spacer = ''
-      (max - k.length).times do
-        spacer += ' '
-      end
-      output.push("#{spacer}#{k}:#{v.time_string(format: :hm)}")
-    end
-
-    header = '┏━━ Tag Totals '
-    (max - 2).times { header += '' }
-    header += ''
-    footer = ''
-    (max + 12).times { footer += '' }
-    footer += ''
-    divider = ''
-    (max + 12).times { divider += '' }
-    divider += ''
-    output = output.empty? ? '' : "\n#{header}\n#{output.join("\n")}"
-    output += "\n#{divider}"
-    spacer = ''
-    (max - 6).times do
-      spacer += ' '
-    end
-    total_time = total.time_string(format: :hm)
-    total = "#{spacer}total: "
-    total += total_time
-    total += ''
-    output += "\n#{total}"
-    output += "\n#{footer}"
-    output
-  else
-    output = []
-    sorted_tags_data.reverse.each do |k, v|
-      spacer = ''
-      (max - k.length).times do
-        spacer += ' '
-      end
-      output.push("#{k}:#{spacer}#{v.time_string(format: :clock)}")
-    end
-
-    output = output.empty? ? '' : "\n--- Tag Totals ---\n#{output.join("\n")}"
-    output += "\n\nTotal tracked: #{total.time_string(format: :clock)}\n"
-    output
-  end
-end
-
+
@@ -8980,117 +4890,7 @@

-

- - - - -
-
-
-
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-
-
# File 'lib/doing/wwid/display.rb', line 137
-
-def today(times = true, output = nil, opt)
-  opt ||= {}
-  opt[:totals] ||= false
-  opt[:sort_tags] ||= false
-
-  cfg = Doing.setting('templates')
-             .deep_merge(Doing.setting('templates.default'), {
-                           extend_existing_arrays: true,
-                           sort_merged_arrays: true
-                         }).deep_merge({
-                                         'wrap_width' => Doing.setting('wrap_width') || 0,
-                                         'date_format' => Doing.setting('default_date_format'),
-                                         'order' => Doing.setting('order') || :asc,
-                                         'tags_color' => Doing.setting('tags_color'),
-                                         'duration' => Doing.setting('duration'),
-                                         'interval_format' => Doing.setting('interval_format')
-                                       }, {
-                                         extend_existing_arrays: true,
-                                         sort_merged_arrays: true
-                                       })
-
-  template = opt[:template] || cfg['template']
-
-  opt[:duration] ||= cfg['duration'] || false
-  opt[:interval_format] ||= cfg['interval_format'] || 'text'
-
-  options = {
-    after: opt[:after],
-    before: opt[:before],
-    count: 0,
-    duration: opt[:duration],
-    from: opt[:from],
-    format: cfg['date_format'],
-    interval_format: opt[:interval_format],
-    only_timed: opt[:only_timed],
-    order: cfg['order'] || :asc,
-    output: output,
-    section: opt[:section],
-    sort_tags: opt[:sort_tags],
-    template: template,
-    times: times,
-    today: true,
-    totals: opt[:totals],
-    wrap_width: cfg['wrap_width'],
-    tags_color: cfg['tags_color'],
-    config_template: opt[:config_template]
-  }
-  list_section(options)
-end
-
+
@@ -9163,63 +4963,7 @@

-

- - - - -
-
-
-
-359
-360
-361
-362
-363
-364
-365
-366
-367
-368
-369
-370
-371
-372
-373
-374
-375
-376
-377
-378
-379
-380
-
-
# File 'lib/doing/wwid/interactive.rb', line 359
-
-def verify_duration(date, finish_date, title: nil)
-  max_elapsed = Doing.setting('interaction.confirm_longer_than', 0)
-  max_elapsed = max_elapsed.chronify_qty if max_elapsed.is_a?(String)
-  date = date.chronify(guess: :end, context: :today) if date.is_a?(String)
-  finish_date = finish_date.chronify(guess: :end, context: :today) if finish_date.is_a?(String)
-
-  elapsed = finish_date - date
-
-  if max_elapsed.positive? && (elapsed > max_elapsed)
-    puts boldwhite(title) if title
-    human = elapsed.time_string(format: :natural)
-    res = Prompt.yn(yellow("Did this entry actually take #{human}"), default_response: true)
-    unless res
-      new_elapsed = Prompt.enter_text('How long did it take?').chronify_qty
-      raise InvalidTimeExpression, 'Unrecognized time span entry' unless new_elapsed.positive?
-
-      finish_date = date + new_elapsed if new_elapsed
-    end
-  end
-
-  finish_date
-end
-
+
@@ -9231,33 +4975,7 @@

-

- - - - -
-
-
-
-119
-120
-121
-122
-123
-124
-125
-
-
# File 'lib/doing/wwid/wwid.rb', line 119
-
-def view_to_options(title)
-  view = rename_view_keys(get_view(guess_view(title)))
-  view.deep_merge(rename_view_keys(get_view(guess_view(view[:parent]), fallback: {}))) if view.key?(:parent)
-  view.deep_merge(rename_view_keys(get_view(view[:config_template], fallback: {}))) if view.key?(:config_template)
-  view.deep_merge(Doing.setting('templates.default').symbolize_keys)
-  view
-end
-
+
@@ -9296,25 +5014,7 @@

-

- - - - -
-
-
-
-94
-95
-96
-
-
# File 'lib/doing/wwid/wwid.rb', line 94
-
-def views
-  Doing.setting('views') ? Doing.setting('views').keys : []
-end
-
+
@@ -9357,39 +5057,7 @@

-

- - - - -
-
-
-
-91
-92
-93
-94
-95
-96
-97
-98
-99
-100
-
-
# File 'lib/doing/wwid/filetools.rb', line 91
-
-def write(file = nil, backup: true)
-  Hooks.trigger :pre_write, self, file
-  output = combined_content
-  if file.nil?
-    $stdout.puts output
-  else
-    Util.write_to_file(file, output, backup: backup)
-    run_after if Doing.setting('run_after')
-  end
-end
-
+
@@ -9479,57 +5147,7 @@

-

- - - - -
-
-
-
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-
-
# File 'lib/doing/wwid/display.rb', line 195
-
-def yesterday(section, times = nil, output = nil, opt)
-  opt ||= {}
-  opt[:totals] ||= false
-  opt[:sort_tags] ||= false
-  opt[:config_template] ||= 'today'
-  opt[:yesterday] = true
-
-  section = guess_section(section)
-  y = (Time.now - (60 * 60 * 24)).strftime('%Y-%m-%d')
-  opt[:after] = "#{y} #{opt[:after]}" if opt[:after]
-  opt[:before] = "#{y} #{opt[:before]}" if opt[:before]
-
-  opt[:output] = output
-  opt[:section] = section
-  opt[:times] = times
-  opt[:count] = 0
-
-  list_section(opt)
-end
-
+ @@ -9537,7 +5155,7 @@

diff --git a/docs/doc/FalseClass.html b/docs/doc/FalseClass.html index 8618275a..beb85c17 100644 --- a/docs/doc/FalseClass.html +++ b/docs/doc/FalseClass.html @@ -215,25 +215,7 @@

- - - - - -
-
-
-
-72
-73
-74
-
-
# File 'lib/doing/good.rb', line 72
-
-def good?
-  false
-end
-
+
@@ -245,25 +227,7 @@

-

- - - - -
-
-
-
-76
-77
-78
-
-
# File 'lib/doing/good.rb', line 76
-
-def normalize_tag_sort
-  :time
-end
-
+

@@ -271,7 +235,7 @@

diff --git a/docs/doc/GLI.html b/docs/doc/GLI.html index 0634bc69..656e2275 100644 --- a/docs/doc/GLI.html +++ b/docs/doc/GLI.html @@ -107,7 +107,7 @@

Defined Under Namespace

diff --git a/docs/doc/GLI/Commands.html b/docs/doc/GLI/Commands.html index 97cd51d8..22f16e20 100644 --- a/docs/doc/GLI/Commands.html +++ b/docs/doc/GLI/Commands.html @@ -107,7 +107,7 @@

Defined Under Namespace

diff --git a/docs/doc/GLI/Commands/Help.html b/docs/doc/GLI/Commands/Help.html index bdc10dff..cacfa1a1 100644 --- a/docs/doc/GLI/Commands/Help.html +++ b/docs/doc/GLI/Commands/Help.html @@ -167,65 +167,7 @@

-

- - - - -
-
-
-
-7
-8
-9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-
-
# File 'lib/doing/help_monkey_patch.rb', line 7
-
-def show_help(global_options, options, arguments, out, error)
-  Doing::Pager.paginate = true
-
-  command_finder = HelpModules::CommandFinder.new(@app, arguments, error)
-  if options[:c]
-    help_output = HelpModules::HelpCompletionFormat.new(@app, command_finder, arguments).format
-    out.puts help_output unless help_output.nil?
-  elsif arguments.empty? || options[:c]
-    Doing::Pager.page HelpModules::GlobalHelpFormat.new(@app, @sorter, @text_wrapping_class).format
-  else
-    name = arguments.shift
-    command = command_finder.find_command(name)
-    unless command.nil?
-      Doing::Pager.page HelpModules::CommandHelpFormat.new(
-        command,
-        @app,
-        @sorter,
-        @synopsis_formatter_class,
-        @text_wrapping_class
-      ).format
-    end
-  end
-end
-
+ @@ -233,7 +175,7 @@

diff --git a/docs/doc/GLI/Commands/MarkdownDocumentListener.html b/docs/doc/GLI/Commands/MarkdownDocumentListener.html index 005a83e0..3de62842 100644 --- a/docs/doc/GLI/Commands/MarkdownDocumentListener.html +++ b/docs/doc/GLI/Commands/MarkdownDocumentListener.html @@ -490,41 +490,7 @@

-
- - - - -
-
-
-
-9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-
-
# File 'lib/doing/markdown_document_listener.rb', line 9
-
-def initialize(_global_options, _options, _arguments, app)
-  @exe = app.exe_name
-  if File.exist?('COMMANDS.md') # Back up existing README
-    FileUtils.mv('COMMANDS.md', 'COMMANDS.bak')
-    $stderr.puts "Backing up existing COMMANDS.md"
-  end
-  @io = File.new('COMMANDS.md', 'w')
-  @nest = '#'
-  @arg_name_formatter = GLI::Commands::HelpModules::ArgNameFormatter.new
-  @parent_command = []
-end
-
+ @@ -543,23 +509,7 @@

-

- - - - -
-
-
-
-21
-22
-
-
# File 'lib/doing/markdown_document_listener.rb', line 21
-
-def beginning
-end
-
+
@@ -581,43 +531,7 @@

-
- - - - -
-
-
-
-118
-119
-120
-121
-122
-123
-124
-125
-126
-127
-128
-129
-
-
# File 'lib/doing/markdown_document_listener.rb', line 118
-
-def command(name, aliases, desc, long_desc, arg_name, arg_options)
-  @parent_command.push ([name] + aliases).join('|')
-  arg_name_fmt = @arg_name_formatter.format(arg_name, arg_options, [])
-  arg_name_fmt = " `#{arg_name_fmt.strip}`" if arg_name_fmt
-  @io.puts header("`$ #{@exe}` <mark>`#{@parent_command.join(' ')}`</mark>#{arg_name_fmt}", 1)
-  @io.puts
-  @io.puts "*#{String(desc).strip}*"
-  @io.puts
-  cmd_desc = String(long_desc).strip.split("\n").map { |_| "> #{_}" }.join("\n")
-  @io.puts "#{cmd_desc}\n\n" unless cmd_desc.length == 0
-  increment_nest
-end
-
+

@@ -629,29 +543,7 @@

-

- - - - -
-
-
-
-111
-112
-113
-114
-115
-
-
# File 'lib/doing/markdown_document_listener.rb', line 111
-
-def commands
-  @io.puts header("Commands", 1)
-  @io.puts
-  increment_nest
-end
-
+
@@ -673,25 +565,7 @@

-
- - - - -
-
-
-
-139
-140
-141
-
-
# File 'lib/doing/markdown_document_listener.rb', line 139
-
-def default_command(name)
-  @io.puts "#### [Default Command] #{name}" unless name.nil?
-end
-
+

@@ -713,29 +587,7 @@

-
- - - - -
-
-
-
-132
-133
-134
-135
-136
-
-
# File 'lib/doing/markdown_document_listener.rb', line 132
-
-def end_command(_name)
-  @parent_command.pop
-  decrement_nest
-  @io.puts "* * * * * *\n\n" unless @nest.size > 2
-end
-
+

@@ -747,25 +599,7 @@

-

- - - - -
-
-
-
-143
-144
-145
-
-
# File 'lib/doing/markdown_document_listener.rb', line 143
-
-def end_commands
-  decrement_nest
-end
-
+
@@ -777,23 +611,7 @@

-

- - - - -
-
-
-
-108
-109
-
-
# File 'lib/doing/markdown_document_listener.rb', line 108
-
-def end_options
-end
-
+
@@ -815,59 +633,7 @@

-
- - - - -
-
-
-
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-
-
# File 'lib/doing/markdown_document_listener.rb', line 25
-
-def ending
-  if File.exist?('CREDITS.md')
-    @io.puts IO.read('CREDITS.md')
-    @io.puts
-  end
-
-  if File.exist?('AUTHORS.md')
-    @io.puts IO.read('AUTHORS.md')
-    @io.puts
-  end
-
-  if File.exist?('LICENSE.md')
-    @io.puts IO.read('LICENSE.md')
-    @io.puts
-  end
-  @io.puts
-  @io.puts "Documentation generated #{Time.now.strftime('%Y-%m-%d %H:%M')}"
-  @io.puts
-  @io.close
-end
-
+

@@ -889,43 +655,7 @@

-
- - - - -
-
-
-
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-
-
# File 'lib/doing/markdown_document_listener.rb', line 80
-
-def flag(name, aliases, desc, long_desc, default_value, arg_name, must_match, _type)
-  invocations = ([name] + Array(aliases)).map { |_| "`" + add_dashes(_) + "`" }.join(' | ')
-  usage = "#{invocations} #{arg_name || 'arg'}"
-  @io.puts header(usage, 2)
-  @io.puts
-  @io.puts String(desc).strip
-  @io.puts "\n*Default Value:* `#{default_value || 'None'}`\n" unless default_value.nil?
-  @io.puts "\n*Must Match:* `#{must_match.to_s}`\n" unless must_match.nil?
-  cmd_desc = String(long_desc).strip
-  @io.puts "> #{cmd_desc}\n" unless cmd_desc.length == 0
-  @io.puts
-end
-
+

@@ -937,35 +667,7 @@

-

- - - - -
-
-
-
-70
-71
-72
-73
-74
-75
-76
-77
-
-
# File 'lib/doing/markdown_document_listener.rb', line 70
-
-def options
-  if @nest.size == 1
-    @io.puts "## Global Options"
-  else
-    @io.puts header("Options", 1)
-  end
-  @io.puts
-end
-
+
@@ -987,31 +689,7 @@

-
- - - - -
-
-
-
-47
-48
-49
-50
-51
-52
-
-
# File 'lib/doing/markdown_document_listener.rb', line 47
-
-def program_desc(desc)
-  @io.puts "# #{@exe} CLI"
-  @io.puts
-  @io.puts desc
-  @io.puts
-end
-
+

@@ -1023,27 +701,7 @@

-

- - - - -
-
-
-
-54
-55
-56
-57
-
-
# File 'lib/doing/markdown_document_listener.rb', line 54
-
-def program_long_desc(desc)
-  @io.puts "> #{desc}"
-  @io.puts
-end
-
+
@@ -1065,45 +723,7 @@

-
- - - - -
-
-
-
-94
-95
-96
-97
-98
-99
-100
-101
-102
-103
-104
-105
-106
-
-
# File 'lib/doing/markdown_document_listener.rb', line 94
-
-def switch(name, aliases, desc, long_desc, negatable)
-  if negatable
-    name = "[no-]#{name}" if name.to_s.length > 1
-    aliases = aliases.map { |_|  _.to_s.length > 1 ? "[no-]#{_}" : _ }
-  end
-  invocations = ([name] + aliases).map { |_| "`" + add_dashes(_).strip + "`" }.join('|')
-  @io.puts header("#{invocations}", 2)
-  @io.puts
-  @io.puts String(desc).strip
-  cmd_desc = String(long_desc).strip
-  @io.puts "\n> #{cmd_desc}\n" unless cmd_desc.length == 0
-  @io.puts
-end
-
+

@@ -1125,37 +745,7 @@

-
- - - - -
-
-
-
-60
-61
-62
-63
-64
-65
-66
-67
-68
-
-
# File 'lib/doing/markdown_document_listener.rb', line 60
-
-def version(version)
-  @io.puts "*v#{version}*"
-  @io.puts
-  # Hacking in the overview file
-  if File.exist?('OVERVIEW.md')
-    @io.puts IO.read('OVERVIEW.md')
-    @io.puts
-  end
-end
-
+

@@ -1163,7 +753,7 @@

diff --git a/docs/doc/Hash.html b/docs/doc/Hash.html index 4b5a6d7d..b59e9c52 100644 --- a/docs/doc/Hash.html +++ b/docs/doc/Hash.html @@ -482,25 +482,7 @@

-

- - - - -
-
-
-
-37
-38
-39
-
-
# File 'lib/doing/hash.rb', line 37
-
-def clone
-  Marshal.load(Marshal.dump(self))
-end
-
+
@@ -539,35 +521,7 @@

-

- - - - -
-
-
-
-11
-12
-13
-14
-15
-16
-17
-18
-
-
# File 'lib/doing/hash.rb', line 11
-
-def deep_freeze
-  chilled = {}
-  each do |k, v|
-    chilled[k] = v.is_a?(Hash) ? v.deep_freeze : v.freeze
-  end
-
-  chilled.freeze
-end
-
+
@@ -579,25 +533,7 @@

-

- - - - -
-
-
-
-20
-21
-22
-
-
# File 'lib/doing/hash.rb', line 20
-
-def deep_freeze!
-  replace deep_thaw.deep_freeze
-end
-
+
@@ -662,71 +598,7 @@

Examples:

-
- - - - -
-
-
-
-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
-
-
# File 'lib/doing/hash.rb', line 100
-
-def deep_set(path, value)
-  if path.count == 1
-    if value.nil? || (value.is_a?(String) && value =~ /^ *$/) || (value.is_a?(Array) && value.empty?)
-      delete(path[0])
-    else
-      self[path[0]] = value
-    end
-  elsif value
-    self.default_proc = ->(h, k) { h[k] = Hash.new(&h.default_proc) }
-    dig(*path[0..-2])[path.fetch(-1)] = value
-  else
-    return self unless dig(*path)
-
-    dig(*path[0..-2]).delete(path.fetch(-1))
-    path.pop
-    cleaned = self
-    path.each do |key|
-      if cleaned[key].empty?
-        cleaned.delete(key)
-        break
-      end
-      cleaned = cleaned[key]
-    end
-    empty? ? nil : self
-  end
-end
-
+
@@ -738,35 +610,7 @@

-

- - - - -
-
-
-
-24
-25
-26
-27
-28
-29
-30
-31
-
-
# File 'lib/doing/hash.rb', line 24
-
-def deep_thaw
-  chilled = {}
-  each do |k, v|
-    chilled[k] = v.is_a?(Hash) ? v.deep_thaw : v.dup
-  end
-
-  chilled.dup
-end
-
+
@@ -778,25 +622,7 @@

-

- - - - -
-
-
-
-33
-34
-35
-
-
# File 'lib/doing/hash.rb', line 33
-
-def deep_thaw!
-  replace deep_thaw
-end
-
+
@@ -852,29 +678,7 @@

-

- - - - -
-
-
-
-195
-196
-197
-198
-199
-
-
# File 'lib/doing/hash.rb', line 195
-
-def delete_unless_key(key, to_delete)
-  unless key?(key)
-    to_delete.each { |k| delete(k) }
-  end
-end
-
+
@@ -896,25 +700,7 @@

-
- - - - -
-
-
-
-155
-156
-157
-
-
# File 'lib/doing/hash.rb', line 155
-
-def remove_empty
-  delete_if { |k, v| !v.is_a?(FalseClass) && !v.good? }
-end
-
+

@@ -988,33 +774,7 @@

-

- - - - -
-
-
-
-135
-136
-137
-138
-139
-140
-141
-
-
# File 'lib/doing/hash.rb', line 135
-
-def rename_key(old_key, new_key, keep: false)
-  return unless key?(old_key)
-
-  self[new_key] = self[old_key]
-  self[new_key.to_s] = self[old_key] if key?(new_key.to_s)
-  delete(old_key) unless keep
-end
-
+
@@ -1055,25 +815,7 @@

-

- - - - -
-
-
-
-148
-149
-150
-
-
# File 'lib/doing/hash.rb', line 148
-
-def rename_keys(*pairs)
-  pairs.each { |p| rename_key(p[0], p[1]) }
-end
-
+
@@ -1116,33 +858,7 @@

-

- - - - -
-
-
-
-49
-50
-51
-52
-53
-54
-55
-
-
# File 'lib/doing/hash.rb', line 49
-
-def stringify_keys
-  each_with_object({}) do |(k, v), hsh|
-    next if k.is_a?(Symbol) && key?(k.to_s)
-
-    hsh[k.to_s] = v.is_a?(Hash) ? v.stringify_keys : v
-  end
-end
-
+
@@ -1182,41 +898,7 @@

-

- - - - -
-
-
-
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-
-
# File 'lib/doing/hash.rb', line 79
-
-def stringify_values
-  transform_values do |v|
-    if v.is_a?(Hash)
-      v.stringify_values
-    elsif v.is_a?(Symbol)
-      v.to_s
-    else
-      v
-    end
-  end
-end
-
+
@@ -1259,33 +941,7 @@

-

- - - - -
-
-
-
-65
-66
-67
-68
-69
-70
-71
-
-
# File 'lib/doing/hash.rb', line 65
-
-def symbolize_keys
-  each_with_object({}) do |(k, v), hsh|
-    next if k.is_a?(String) && key?(k.to_sym)
-
-    hsh[k.to_sym] = v.is_a?(Hash) ? v.symbolize_keys : v
-  end
-end
-
+
@@ -1297,37 +953,7 @@

-

- - - - -
-
-
-
-159
-160
-161
-162
-163
-164
-165
-166
-167
-
-
# File 'lib/doing/hash.rb', line 159
-
-def tag_filter_to_options
-  hsh = dup
-  if hsh.key?(:tag_filter) && hsh[:tag_filter]
-    hsh[:tags] = hsh[:tag_filter][:tags]
-    hsh[:bool] = hsh[:tag_filter][:bool]
-    hsh.delete(:tag_filter)
-  end
-  replace hsh
-end
-
+
@@ -1366,47 +992,7 @@

-

- - - - -
-
-
-
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-
-
# File 'lib/doing/hash.rb', line 174
-
-def to_view
-  hsh = symbolize_keys
-  %i[x save c a s o h e editor m menu i interactive d delete t fuzzy time_filter sort_tags].each do |key|
-    hsh.delete(key) if hsh.key?(key)
-  end
-
-  hsh.delete_unless_key(:tag, %i[bool])
-  hsh.delete_unless_key(:search, %i[exact case])
-  hsh.rename_keys(%i[not negate], %i[tag tags])
-  hsh.tag_filter_to_options
-
-  hsh = hsh.remove_empty.stringify_keys.stringify_values
-  hsh.keys.sort.each_with_object({}) { |k, out| out[k] = hsh[k] }
-end
-
+ @@ -1414,7 +1000,7 @@

diff --git a/docs/doc/Numeric.html b/docs/doc/Numeric.html index f84180ab..ab454b5a 100644 --- a/docs/doc/Numeric.html +++ b/docs/doc/Numeric.html @@ -206,25 +206,7 @@

- - - - - -
-
-
-
-7
-8
-9
-
-
# File 'lib/doing/good.rb', line 7
-
-def good?
-  self >= 0
-end
-
+ @@ -232,7 +214,7 @@

diff --git a/docs/doc/Object.html b/docs/doc/Object.html index b7546148..3a1fe6e0 100644 --- a/docs/doc/Object.html +++ b/docs/doc/Object.html @@ -185,25 +185,7 @@

- - - - - -
-
-
-
-20
-21
-22
-
-
# File 'lib/doing/good.rb', line 20
-
-def good?
-  !nil? && !self&.empty? || false
-end
-
+ @@ -211,7 +193,7 @@

diff --git a/docs/doc/PhraseParser.html b/docs/doc/PhraseParser.html index 39b26edf..9996dd7a 100644 --- a/docs/doc/PhraseParser.html +++ b/docs/doc/PhraseParser.html @@ -105,7 +105,7 @@

Defined Under Namespace

diff --git a/docs/doc/PhraseParser/Operator.html b/docs/doc/PhraseParser/Operator.html index d734237b..7a703ca1 100644 --- a/docs/doc/PhraseParser/Operator.html +++ b/docs/doc/PhraseParser/Operator.html @@ -154,43 +154,7 @@

-

- - - - -
-
-
-
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-
-
# File 'lib/doing/phrase_parser.rb', line 37
-
-def self.symbol(str)
-  case str
-  when '+'
-    :must
-  when '-'
-    :must_not
-  when nil
-    :should
-  else
-    raise "Unknown operator: #{str}"
-  end
-end
-
+ @@ -198,7 +162,7 @@

diff --git a/docs/doc/PhraseParser/PhraseClause.html b/docs/doc/PhraseParser/PhraseClause.html index 204b5ce0..187c82fd 100644 --- a/docs/doc/PhraseParser/PhraseClause.html +++ b/docs/doc/PhraseParser/PhraseClause.html @@ -231,27 +231,7 @@

-
- - - - -
-
-
-
-64
-65
-66
-67
-
-
# File 'lib/doing/phrase_parser.rb', line 64
-
-def initialize(operator, phrase)
-  self.operator = Operator.symbol(operator)
-  self.phrase = phrase
-end
-
+ @@ -280,25 +260,7 @@

-
- - - - -
-
-
-
-62
-63
-64
-
-
# File 'lib/doing/phrase_parser.rb', line 62
-
-def operator
-  @operator
-end
-
+ @@ -322,25 +284,7 @@

-
- - - - -
-
-
-
-62
-63
-64
-
-
# File 'lib/doing/phrase_parser.rb', line 62
-
-def phrase
-  @phrase
-end
-
+ @@ -349,7 +293,7 @@

diff --git a/docs/doc/PhraseParser/Query.html b/docs/doc/PhraseParser/Query.html index 90f345d6..b76782fa 100644 --- a/docs/doc/PhraseParser/Query.html +++ b/docs/doc/PhraseParser/Query.html @@ -345,31 +345,7 @@

-
- - - - -
-
-
-
-74
-75
-76
-77
-78
-79
-
-
# File 'lib/doing/phrase_parser.rb', line 74
-
-def initialize(clauses)
-  grouped = clauses.chunk(&:operator).to_h
-  self.should_clauses = grouped.fetch(:should, [])
-  self.must_not_clauses = grouped.fetch(:must_not, [])
-  self.must_clauses = grouped.fetch(:must, [])
-end
-
+ @@ -398,25 +374,7 @@

-
- - - - -
-
-
-
-72
-73
-74
-
-
# File 'lib/doing/phrase_parser.rb', line 72
-
-def must_clauses
-  @must_clauses
-end
-
+ @@ -440,25 +398,7 @@

-
- - - - -
-
-
-
-72
-73
-74
-
-
# File 'lib/doing/phrase_parser.rb', line 72
-
-def must_not_clauses
-  @must_not_clauses
-end
-
+ @@ -482,25 +422,7 @@

-
- - - - -
-
-
-
-72
-73
-74
-
-
# File 'lib/doing/phrase_parser.rb', line 72
-
-def should_clauses
-  @should_clauses
-end
-
+ @@ -519,39 +441,7 @@

-

- - - - -
-
-
-
-105
-106
-107
-108
-109
-110
-111
-112
-113
-114
-
-
# File 'lib/doing/phrase_parser.rb', line 105
-
-def clause_to_query(clause)
-  case clause
-  when TermClause
-    match(clause.term)
-  when PhraseClause
-    match_phrase(clause.phrase)
-  else
-    raise "Unknown clause type: #{clause}"
-  end
-end
-
+
@@ -563,25 +453,7 @@

-

- - - - -
-
-
-
-116
-117
-118
-
-
# File 'lib/doing/phrase_parser.rb', line 116
-
-def match(term)
-  term
-end
-
+
@@ -593,25 +465,7 @@

-

- - - - -
-
-
-
-120
-121
-122
-
-
# File 'lib/doing/phrase_parser.rb', line 120
-
-def match_phrase(phrase)
-  phrase
-end
-
+
@@ -623,65 +477,7 @@

-

- - - - -
-
-
-
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-100
-101
-102
-103
-
-
# File 'lib/doing/phrase_parser.rb', line 81
-
-def to_elasticsearch
-  query = {}
-
-  if should_clauses.any?
-    query[:should] = should_clauses.map do |clause|
-      clause_to_query(clause)
-    end
-  end
-
-  if must_clauses.any?
-    query[:must] = must_clauses.map do |clause|
-      clause_to_query(clause)
-    end
-  end
-
-  if must_not_clauses.any?
-    query[:must_not] = must_not_clauses.map do |clause|
-      clause_to_query(clause)
-    end
-  end
-
-  query
-end
-
+
@@ -689,7 +485,7 @@

diff --git a/docs/doc/PhraseParser/QueryParser.html b/docs/doc/PhraseParser/QueryParser.html index f17b80de..686f1f7e 100644 --- a/docs/doc/PhraseParser/QueryParser.html +++ b/docs/doc/PhraseParser/QueryParser.html @@ -126,7 +126,7 @@

Overview

diff --git a/docs/doc/PhraseParser/QueryTransformer.html b/docs/doc/PhraseParser/QueryTransformer.html index 428b6d48..29da8b44 100644 --- a/docs/doc/PhraseParser/QueryTransformer.html +++ b/docs/doc/PhraseParser/QueryTransformer.html @@ -114,7 +114,7 @@ diff --git a/docs/doc/PhraseParser/TermClause.html b/docs/doc/PhraseParser/TermClause.html index 8a9763c9..90487f62 100644 --- a/docs/doc/PhraseParser/TermClause.html +++ b/docs/doc/PhraseParser/TermClause.html @@ -221,27 +221,7 @@

-
- - - - -
-
-
-
-54
-55
-56
-57
-
-
# File 'lib/doing/phrase_parser.rb', line 54
-
-def initialize(operator, term)
-  self.operator = Operator.symbol(operator)
-  self.term = term
-end
-
+ @@ -270,25 +250,7 @@

-
- - - - -
-
-
-
-52
-53
-54
-
-
# File 'lib/doing/phrase_parser.rb', line 52
-
-def operator
-  @operator
-end
-
+ @@ -312,25 +274,7 @@

-
- - - - -
-
-
-
-52
-53
-54
-
-
# File 'lib/doing/phrase_parser.rb', line 52
-
-def term
-  @term
-end
-
+ @@ -339,7 +283,7 @@

diff --git a/docs/doc/Status.html b/docs/doc/Status.html index cb683476..7f7a4967 100644 --- a/docs/doc/Status.html +++ b/docs/doc/Status.html @@ -248,25 +248,7 @@

-

- - - - -
-
-
-
-25
-26
-27
-
-
# File 'lib/doing/cli_status.rb', line 25
-
-def clear
-  $stderr.print format("\r#{esc['kill']}")
-end
-
+
@@ -278,25 +260,7 @@

-

- - - - -
-
-
-
-2
-3
-4
-
-
# File 'lib/doing/cli_status.rb', line 2
-
-def cols
-  @cols ||= `tput cols`.strip.to_i
-end
-
+
@@ -308,109 +272,7 @@

-

- - - - -
-
-
-
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-
-
# File 'lib/doing/cli_status.rb', line 29
-
-def esc
-  e = {}
-  e['kill'] = "\033[2K"
-  e['reset'] = "\033[A\033[2K"
-  e['black'] = "\033[0;0;30m"
-  e['red'] = "\033[0;0;31m"
-  e['green'] = "\033[0;0;32m"
-  e['yellow'] = "\033[0;0;33m"
-  e['blue'] = "\033[0;0;34m"
-  e['magenta'] = "\033[0;0;35m"
-  e['cyan'] = "\033[0;0;36m"
-  e['white'] = "\033[0;0;37m"
-  e['bgblack'] = "\033[40m"
-  e['bgred'] = "\033[41m"
-  e['bggreen'] = "\033[42m"
-  e['bgyellow'] = "\033[43m"
-  e['bgblue'] = "\033[44m"
-  e['bgmagenta'] = "\033[45m"
-  e['bgcyan'] = "\033[46m"
-  e['bgwhite'] = "\033[47m"
-  e['boldblack'] = "\033[1;30m"
-  e['boldred'] = "\033[1;31m"
-  e['boldgreen'] = "\033[0;1;32m"
-  e['boldyellow'] = "\033[0;1;33m"
-  e['boldblue'] = "\033[0;1;34m"
-  e['boldmagenta'] = "\033[0;1;35m"
-  e['boldcyan'] = "\033[0;1;36m"
-  e['boldwhite'] = "\033[0;1;37m"
-  e['boldbgblack'] = "\033[1;40m"
-  e['boldbgred'] = "\033[1;41m"
-  e['boldbggreen'] = "\033[1;42m"
-  e['boldbgyellow'] = "\033[1;43m"
-  e['boldbgblue'] = "\033[1;44m"
-  e['boldbgmagenta'] = "\033[1;45m"
-  e['boldbgcyan'] = "\033[1;46m"
-  e['boldbgwhite'] = "\033[1;47m"
-  e['softpurple'] = "\033[0;35;40m"
-  e['hotpants'] = "\033[7;34;40m"
-  e['knightrider'] = "\033[7;30;40m"
-  e['flamingo'] = "\033[7;31;47m"
-  e['yeller'] = "\033[1;37;43m"
-  e['whiteboard'] = "\033[1;30;47m"
-  e['default'] = "\033[0;39m"
-  e
-end
-
+
@@ -422,25 +284,7 @@

-

- - - - -
-
-
-
-21
-22
-23
-
-
# File 'lib/doing/cli_status.rb', line 21
-
-def msg(msg, reset: true, color: 'green', end_char: "\n")
-  $stderr.print format("#{esc['kill']}#{esc[color]}%s#{esc['default']}%s", msg, reset ? "\r" : end_char)
-end
-
+
@@ -452,39 +296,7 @@

-

- - - - -
-
-
-
-6
-7
-8
-9
-10
-11
-12
-13
-14
-15
-
-
# File 'lib/doing/cli_status.rb', line 6
-
-def progress(msg, idx, total, tail = [])
-  status_width = format("> %s [%#{total.to_s.length}d/%d]: ", msg, 0, total).length
-  max_width = cols - status_width
-  if tail.is_a? Array
-    tail.shift while tail.join(', ').length + 3 > max_width
-    tail = tail.join(', ')
-  end
-  tail.ltrunc!(max_width)
-  $stderr.print format("#{esc['kill']}#{esc['boldyellow']}> #{esc['boldgreen']}%s #{esc['white']}[#{esc['boldwhite']}%#{@commands.count.to_s.length}d#{esc['boldblack']}/#{esc['boldyellow']}%d#{esc['white']}]: #{esc['boldcyan']}%s#{esc['default']}\r", msg, idx, total, tail)
-end
-
+
@@ -496,25 +308,7 @@

-

- - - - -
-
-
-
-17
-18
-19
-
-
# File 'lib/doing/cli_status.rb', line 17
-
-def status(msg, reset: true, end_char: "\n")
-  $stderr.print format("#{esc['kill']}#{esc['boldyellow']}> #{esc['whiteboard']}%s#{esc['default']}%s", msg, reset ? "\r" : end_char)
-end
-
+
@@ -522,7 +316,7 @@

diff --git a/docs/doc/String.html b/docs/doc/String.html index 44d237ec..4d1ac476 100644 --- a/docs/doc/String.html +++ b/docs/doc/String.html @@ -457,25 +457,7 @@

- - - - - -
-
-
-
-46
-47
-48
-
-
# File 'lib/doing/good.rb', line 46
-
-def good?
-  !strip.empty?
-end
-
+
@@ -515,119 +497,7 @@

-

- - - - -
-
-
-
-135
-136
-137
-138
-139
-140
-141
-142
-143
-144
-145
-146
-147
-148
-149
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-
-
# File 'lib/doing/colors.rb', line 135
-
-def last_color_code
-  m = scan(ESCAPE_REGEX)
-
-  em = ['0']
-  fg = nil
-  bg = nil
-  rgbf = nil
-  rgbb = nil
-
-  m.each do |c|
-    case c
-    when '0'
-      em = ['0']
-      fg, bg, rgbf, rgbb = nil
-    when /^[34]8/
-      case c
-      when /^3/
-        fg = nil
-        rgbf = c
-      when /^4/
-        bg = nil
-        rgbb = c
-      end
-    else
-      c.split(/;/).each do |i|
-        x = i.to_i
-        if x <= 9
-          em << x
-        elsif x >= 30 && x <= 39
-          rgbf = nil
-          fg = x
-        elsif x >= 40 && x <= 49
-          rgbb = nil
-          bg = x
-        elsif x >= 90 && x <= 97
-          rgbf = nil
-          fg = x
-        elsif x >= 100 && x <= 107
-          rgbb = nil
-          bg = x
-        end
-      end
-    end
-  end
-
-  escape = "\e[#{em.join(';')}m"
-  escape += "\e[#{rgbb}m" if rgbb
-  escape += "\e[#{rgbf}m" if rgbf
-  escape + "\e[#{[fg, bg].delete_if(&:nil?).join(';')}m"
-end
-
+
@@ -668,25 +538,7 @@

-

- - - - -
-
-
-
-126
-127
-128
-
-
# File 'lib/doing/colors.rb', line 126
-
-def normalize_color
-  gsub(/_/, '').sub(/bright/i, 'bold').sub(/bgbold/, 'boldbg')
-end
-
+
@@ -698,25 +550,7 @@

-

- - - - -
-
-
-
-6
-7
-8
-
-
# File 'lib/doing/completion/fig_completion.rb', line 6
-
-def sanitize
-  gsub(/"/, '\"')
-end
-
+

@@ -755,33 +589,7 @@

-

- - - - -
-
-
-
-33
-34
-35
-36
-37
-38
-39
-
-
# File 'lib/doing/string/string.rb', line 33
-
-def utf8
-  if String.method_defined? :force_encoding
-    dup.force_encoding('utf-8')
-  else
-    self
-  end
-end
-
+
@@ -820,25 +628,7 @@

-

- - - - -
-
-
-
-24
-25
-26
-
-
# File 'lib/doing/string/string.rb', line 24
-
-def valid_id?
-  strip =~ /^[a-z0-9]{32}$/ ? true : false
-end
-
+
@@ -881,39 +671,7 @@

-

- - - - -
-
-
-
-108
-109
-110
-111
-112
-113
-114
-115
-116
-117
-
-
# File 'lib/doing/colors.rb', line 108
-
-def validate_color
-  valid_color = nil
-  compiled = ''
-  normalize_color.split('').each do |char|
-    compiled += char
-    valid_color = compiled if Color.attributes.include?(compiled.to_sym) || compiled =~ /^([fb]g?)?#([a-f0-9]{6})$/i
-  end
-
-  valid_color
-end
-
+ @@ -921,7 +679,7 @@

diff --git a/docs/doc/Symbol.html b/docs/doc/Symbol.html index 5b554852..82764c7e 100644 --- a/docs/doc/Symbol.html +++ b/docs/doc/Symbol.html @@ -127,7 +127,7 @@

Methods included from - Generated on Sun Dec 1 11:01:05 2024 by + Generated on Sat Dec 14 15:35:49 2024 by yard 0.9.37 (ruby-3.3.0). diff --git a/docs/doc/Time.html b/docs/doc/Time.html index f282229b..c911a405 100644 --- a/docs/doc/Time.html +++ b/docs/doc/Time.html @@ -264,25 +264,7 @@

- - - - - -
-
-
-
-33
-34
-35
-
-
# File 'lib/doing/good.rb', line 33
-
-def good?
-  !nil?
-end
-
+
@@ -340,51 +322,7 @@

-

- - - - -
-
-
-
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-
-
# File 'lib/doing/time.rb', line 31
-
-def humanize(seconds)
-  s = seconds
-  m = (s / 60).floor
-  s = (s % 60).floor
-  h = (m / 60).floor
-  m = (m % 60).floor
-  d = (h / 24).floor
-  h = h % 24
-
-  output = []
-  output.push("#{d} #{'day'.to_p(d)}") if d.positive?
-  output.push("#{h} #{'hour'.to_p(h)}") if h.positive?
-  output.push("#{m} #{'minute'.to_p(m)}") if m.positive?
-  output.push("#{s} #{'second'.to_p(s)}") if s.positive?
-  output.join(', ')
-end
-
+
@@ -426,41 +364,7 @@

-

- - - - -
-
-
-
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-
-
# File 'lib/doing/time.rb', line 13
-
-def relative_date
-  if self > Date.today.to_time
-    strftime(Doing.setting('shortdate_format.today', '%_I:%M%P', exact: true))
-  elsif self > (Date.today - 6).to_time
-    strftime(Doing.setting('shortdate_format.this_week', '%a %_I:%M%P', exact: true))
-  elsif year == Date.today.year || (year + 1 == Date.today.year && month > Date.today.month)
-    strftime(Doing.setting('shortdate_format.this_month', '%m/%d %_I:%M%P', exact: true))
-  else
-    strftime(Doing.setting('shortdate_format.older', '%m/%d/%y %_I:%M%P', exact: true))
-  end
-end
-
+
@@ -499,47 +403,7 @@

-

- - - - -
-
-
-
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-
-
# File 'lib/doing/time.rb', line 53
-
-def time_ago
-  if self > Date.today.to_time
-    output = humanize(Time.now - self)
-    "#{output} ago"
-  elsif self > (Date.today - 1).to_time
-    "Yesterday at #{strftime('%_I:%M:%S%P')}"
-  elsif self > (Date.today - 6).to_time
-    strftime('%a %I:%M:%S%P')
-  elsif self.year == Date.today.year
-    strftime('%m/%d %I:%M:%S%P')
-  else
-    strftime('%m/%d/%Y %I:%M:%S%P')
-  end
-end
-
+ @@ -547,7 +411,7 @@

diff --git a/docs/doc/TrueClass.html b/docs/doc/TrueClass.html index ff941f8f..2db883ce 100644 --- a/docs/doc/TrueClass.html +++ b/docs/doc/TrueClass.html @@ -215,25 +215,7 @@

- - - - - -
-
-
-
-89
-90
-91
-
-
# File 'lib/doing/good.rb', line 89
-
-def good?
-  true
-end
-
+
@@ -245,25 +227,7 @@

-

- - - - -
-
-
-
-93
-94
-95
-
-
# File 'lib/doing/good.rb', line 93
-
-def normalize_tag_sort
-  :name
-end
-
+

@@ -271,7 +235,7 @@

diff --git a/docs/doc/_index.html b/docs/doc/_index.html index cbdbf4bd..68e26f2e 100644 --- a/docs/doc/_index.html +++ b/docs/doc/_index.html @@ -961,7 +961,7 @@

Namespace Listing A-Z

diff --git a/docs/doc/file.README.html b/docs/doc/file.README.html index 97f52f4a..d04032e0 100644 --- a/docs/doc/file.README.html +++ b/docs/doc/file.README.html @@ -71,7 +71,7 @@ -

The current version of doing is <!--VER-->2.1.85<!--END VER-->.

+

The current version of doing is <!--VER-->2.1.86<!--END VER-->.

Find all of the documentation in the doing wiki.

@@ -153,7 +153,7 @@

Changelog

diff --git a/docs/doc/index.html b/docs/doc/index.html index 069df458..7a080135 100644 --- a/docs/doc/index.html +++ b/docs/doc/index.html @@ -71,7 +71,7 @@ -

The current version of doing is <!--VER-->2.1.85<!--END VER-->.

+

The current version of doing is <!--VER-->2.1.86<!--END VER-->.

Find all of the documentation in the doing wiki.

@@ -153,7 +153,7 @@

Changelog

diff --git a/docs/doc/top-level-namespace.html b/docs/doc/top-level-namespace.html index 521459b6..9f3d803e 100644 --- a/docs/doc/top-level-namespace.html +++ b/docs/doc/top-level-namespace.html @@ -208,425 +208,7 @@

- - - - - -
-
-
-
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-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
-150
-151
-152
-153
-154
-155
-156
-157
-158
-159
-160
-161
-162
-163
-164
-165
-166
-167
-168
-169
-170
-171
-172
-173
-174
-175
-176
-177
-178
-179
-180
-181
-182
-183
-184
-185
-186
-187
-188
-189
-190
-191
-192
-193
-194
-195
-196
-197
-198
-199
-200
-201
-202
-203
-204
-205
-206
-207
-208
-209
-210
-211
-212
-213
-214
-215
-216
-217
-218
-219
-220
-221
-222
-223
-224
-225
-226
-227
-228
-229
-
-
# File 'lib/doing/add_options.rb', line 27
-
-def add_options(type, cmd, default_template: 'default')
-  cmd_name = cmd.name.to_s
-  action = case cmd_name
-           when /again/
-             'Repeat'
-           when /grep/
-             'Search'
-           when /mark/
-             'Flag'
-           when /(last|tags|view|on)/
-             'Show'
-           else
-             cmd_name.capitalize
-           end
-
-  case type
-  when :output_template
-    cmd.desc "Output to export format (#{Doing::Plugins.plugin_names(type: :export)})"
-    cmd.arg_name 'FORMAT'
-    cmd.flag %i[o output], type: ExportTemplate
-
-    cmd.desc "Output using a template from configuration"
-    cmd.arg_name 'TEMPLATE_KEY'
-    cmd.flag [:config_template], type: TemplateName, default_value: default_template
-
-    cmd.desc 'Override output format with a template string containing %placeholders'
-    cmd.arg_name 'TEMPLATE_STRING'
-    cmd.flag [:template]
-  when :output_template_no_defaults
-    cmd.desc "Output to export format (#{Doing::Plugins.plugin_names(type: :export)})"
-    cmd.arg_name 'FORMAT'
-    cmd.flag %i[o output]
-
-    cmd.desc "Output using a template from configuration"
-    cmd.arg_name 'TEMPLATE_KEY'
-    cmd.flag [:config_template], type: TemplateName
-
-    cmd.desc 'Override output format with a template string containing %placeholders'
-    cmd.arg_name 'TEMPLATE_STRING'
-    cmd.flag [:template]
-  when :add_entry
-    cmd.desc 'Exclude auto tags and default tags'
-    cmd.switch %i[X noauto], default_value: false, negatable: false
-
-    cmd.desc 'Include a note'
-    cmd.arg_name 'TEXT'
-    cmd.flag %i[n note]
-
-    cmd.desc 'Prompt for note via multi-line input'
-    cmd.switch %i[ask], negatable: false, default_value: false
-
-    cmd.desc "Edit entry with #{Doing::Util.default_editor}"
-    cmd.switch %i[e editor], negatable: false, default_value: false
-
-    cmd.desc 'Backdate start date for new entry to date string [4pm|20m|2h|yesterday noon]'
-    cmd.arg_name 'DATE_STRING'
-    cmd.flag %i[b back started since], type: DateBeginString
-  when :finish_entry
-    cmd.desc %(Set finish date to specific date/time (natural langauge parsed, e.g. --at=1:30pm).
-    Used with --took, backdates start date)
-    cmd.arg_name 'DATE_STRING'
-    cmd.flag %i[at finished], type: DateEndString
-
-    cmd.desc %(
-          Start and end times as a date/time range `doing done --from "1am to 8am"`.
-          Overrides other date flags.
-        )
-    cmd.arg_name 'TIME_RANGE'
-    cmd.flag [:from], must_match: REGEX_RANGE
-
-    cmd.desc %(Set completion date to start date plus interval (XX[mhd] or HH:MM).
-    If used without the --back option, the start date will be moved back to allow
-    the completion date to be the current time.)
-    cmd.arg_name 'INTERVAL'
-    cmd.flag %i[t took for], type: DateIntervalString
-  when :search
-    cmd.desc 'Filter entries using a search query, surround with slashes for regex (e.g. "/query.*/"),
-            start with single quote for exact match ("\'query")'
-    cmd.arg_name 'QUERY'
-    cmd.flag [:search]
-
-    cmd.desc 'Case sensitivity for search string matching [(c)ase-sensitive, (i)gnore, (s)mart]'
-    cmd.arg_name 'TYPE'
-    cmd.flag [:case], must_match: REGEX_CASE,
-                      default_value: Doing.settings.dig('search', 'case').normalize_case,
-                      type: CaseSymbol
-
-    cmd.desc 'Force exact search string matching (case sensitive)'
-    cmd.switch %i[x exact], default_value: Doing.config.exact_match?, negatable: Doing.config.exact_match?
-  when :time_display
-    cmd.desc 'Show time intervals on @done tasks'
-    cmd.switch %i[t times], default_value: true, negatable: true
-
-    cmd.desc 'Show elapsed time on entries without @done tag'
-    cmd.switch [:duration]
-
-    cmd.desc 'Show time totals at the end of output'
-    cmd.switch [:totals], default_value: false, negatable: false
-
-    cmd.desc 'Sort tags by (name|time)'
-    default = Doing.setting('tag_sort').normalize_tag_sort || :name
-    cmd.arg_name 'KEY'
-    cmd.flag [:tag_sort], must_match: REGEX_TAG_SORT, default_value: default, type: TagSortSymbol
-
-    cmd.desc 'Tag sort direction (asc|desc)'
-    cmd.arg_name 'DIRECTION'
-    cmd.flag [:tag_order], must_match: REGEX_SORT_ORDER, default_value: :asc, type: OrderSymbol
-
-    cmd.desc 'Only show items with recorded time intervals'
-    cmd.switch [:only_timed], default_value: false, negatable: false
-  when :tag_filter
-    cmd.desc 'Filter entries by tag. Combine multiple tags with a comma. Wildcards allowed (*, ?)'
-    cmd.arg_name 'TAG'
-    cmd.flag [:tag], type: TagArray
-
-    cmd.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50").
-            May be used multiple times, combined with --bool'
-    cmd.arg_name 'QUERY'
-    cmd.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
-
-    cmd.desc "#{action} items that *don't* match search/tag filters"
-    cmd.switch [:not], default_value: false, negatable: false
-
-    cmd.desc 'Boolean used to combine multiple tags (AND|OR|NOT). Use PATTERN to parse + and - as booleans'
-    cmd.arg_name 'BOOLEAN'
-    cmd.flag [:bool], must_match: REGEX_BOOL,
-                      default_value: :pattern,
-                      type: BooleanSymbol
-  when :tag_filter_no_defaults
-    cmd.desc 'Filter entries by tag. Combine multiple tags with a comma. Wildcards allowed (*, ?)'
-    cmd.arg_name 'TAG'
-    cmd.flag [:tag], type: TagArray
-
-    cmd.desc 'Perform a tag value query ("@done > two hours ago" or "@progress < 50").
-            May be used multiple times, combined with --bool'
-    cmd.arg_name 'QUERY'
-    cmd.flag [:val], multiple: true, must_match: REGEX_VALUE_QUERY
-
-    cmd.desc "#{action} items that *don't* match search/tag filters"
-    cmd.switch [:not], negatable: false
-
-    cmd.desc 'Boolean used to combine multiple tags. Use PATTERN to parse + and - as booleans'
-    cmd.arg_name 'BOOLEAN'
-    cmd.flag [:bool], must_match: REGEX_BOOL,
-                      type: BooleanSymbol
-  when :time_filter
-    cmd.desc 'View entries before specified time (e.g. 8am, 12:30pm, 15:00)'
-    cmd.arg_name 'TIME_STRING'
-    cmd.flag [:before], type: DateEndString
-
-    cmd.desc 'View entries after specified time (e.g. 8am, 12:30pm, 15:00)'
-    cmd.arg_name 'TIME_STRING'
-    cmd.flag [:after], type: DateBeginString
-
-    cmd.desc %(
-      Time range to show `doing #{cmd.name} --from "12pm to 4pm"`
-    )
-    cmd.arg_name 'TIME_RANGE'
-    cmd.flag [:from], type: DateRangeString, must_match: REGEX_TIME_RANGE
-  when :date_filter
-    if action =~ /Archive/
-      cmd.desc 'Archive entries older than date (natural language).'
-    else
-      cmd.desc "#{action} entries older than date (natural language). If this is only a time (8am, 1:30pm, 15:00), all
-              dates will be included, but entries will be filtered by time of day"
-    end
-    cmd.arg_name 'DATE_STRING'
-    cmd.flag [:before], type: DateBeginString
-
-    if action =~ /Archive/
-      cmd.desc 'Archive entries newer than date (natural language).'
-    else
-      cmd.desc "#{action} entries newer than date (natural language). If this is only a time (8am, 1:30pm, 15:00), all
-              dates will be included, but entries will be filtered by time of day"
-    end
-    cmd.arg_name 'DATE_STRING'
-    cmd.flag [:after], type: DateEndString
-
-    if action =~ /Archive/
-      cmd.desc %(
-          Date range (natural language) to archive: `doing archive --from "1/1/21 to 12/31/21"`.
-        )
-    else
-      cmd.desc %(
-        Date range (natural language) to #{action.downcase}, or a single day to filter on.
-        To specify a range, use "to": `doing #{cmd_name} --from "monday 8am to friday 5pm"`.
-
-        If values are only time(s) (6am to noon) all dates will be included, but entries will be filtered
-        by time of day.
-      )
-    end
-    cmd.arg_name 'DATE_OR_RANGE'
-    cmd.flag [:from], type: DateRangeString
-  when :save
-    cmd.desc 'Save all current command line options as a new view'
-    cmd.arg_name 'VIEW_NAME'
-    cmd.flag %i[save], type: String
-
-    cmd.desc 'Title string to be used for output formats that require it'
-    cmd.arg_name 'TITLE'
-    cmd.flag %i[title], type: String
-  end
-end
-
+ @@ -634,7 +216,7 @@

diff --git a/doing.gemspec b/doing.gemspec index 9892c369..f21d95f3 100644 --- a/doing.gemspec +++ b/doing.gemspec @@ -1,5 +1,5 @@ # Ensure we require the local version and not one we might have installed already -require File.join([File.dirname(__FILE__), 'lib', 'doing', 'version.rb']) +require './lib/doing/version.rb' spec = Gem::Specification.new do |s| s.name = 'doing' s.version = Doing::VERSION @@ -14,9 +14,7 @@ spec = Gem::Specification.new do |s| 'what they accomplished at 2 in the morning.' ].join(' ') s.license = 'MIT' - s.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z`.split("\x0").reject { |f| f.strip =~ %r{^((test|spec|features)/|\.git|buildnotes)} } - end + s.files = `git ls-files -z`.split("\x0").reject { |f| f.strip =~ %r{^((test|spec|features)/|\.git|buildnotes)} } s.require_paths << 'lib' s.extra_rdoc_files = ['README.md'] s.rdoc_options << '--title' << 'doing' << '--main' << 'README.md' << '--markup' << 'markdown' diff --git a/doing.rdoc b/doing.rdoc index 4ffb43de..442bbc44 100644 --- a/doing.rdoc +++ b/doing.rdoc @@ -5,7 +5,7 @@ record of what you've been doing, complete with tag-based time tracking. The command line tool allows you to add entries, annotate with tags and notes, and view your entries with myriad options, with a focus on a "natural" language syntax. -v2.1.86 +v2.1.87 === Global Options === --config_file arg diff --git a/lib/doing/version.rb b/lib/doing/version.rb index 18cf78f1..e3823bb7 100644 --- a/lib/doing/version.rb +++ b/lib/doing/version.rb @@ -1,3 +1,3 @@ module Doing - VERSION = '2.1.86' + VERSION = '2.1.87' end diff --git a/test/doing_unit-time_test.rb b/test/doing_unit-time_test.rb index 82be1ed9..8f4f3a06 100644 --- a/test/doing_unit-time_test.rb +++ b/test/doing_unit-time_test.rb @@ -20,7 +20,7 @@ def teardown def test_relative_date t = Time.parse("#{Time.now.year - 1}-12-21 15:00") - assert_match(%r{12/21 3:00pm}, t.relative_date, 'Relative date should match') + assert_match(%r{12/21/#{(Time.now.year - 1).to_s.sub(/^\d\d/, '')} 3:00pm}, t.relative_date, "Relative date should match") # Breaks if it's the first of the month # t = Time.parse("#{Time.now.year}-#{Time.now.month}-#{Time.now.day - 1} 12:00")