Class: Doing::Item
- Inherits:
-
Object
- Object
- Doing::Item
- Defined in:
- lib/doing/item.rb
Overview
This class describes a single WWID item
Instance Attribute Summary collapse
-
#date ⇒ Object
Returns the value of attribute date.
-
#id ⇒ String
readonly
Generate a hash that represents the entry.
-
#note ⇒ Object
Returns the value of attribute note.
-
#section ⇒ Object
Returns the value of attribute section.
-
#title ⇒ Object
Returns the value of attribute title.
Instance Method Summary collapse
-
#duration ⇒ Object
If the entry doesn't have a @done date, return the elapsed time.
-
#end_date ⇒ Time
Get the value of the item's @done tag.
-
#equal?(other) ⇒ Boolean
Test for equality between items.
-
#initialize(date, title, section, note = nil) ⇒ Item
constructor
Initialize an item with date, title, section, and optional note.
-
#interval ⇒ Object
Get the difference between the item's start date and the value of its @done tag (if present).
-
#move_to(new_section, label: true, log: true) ⇒ Object
Move item from current section to destination section.
-
#overlapping_time?(item_b) ⇒ Boolean
Test if the interval between start date and @done value overlaps with another item's.
-
#same_time?(item_b) ⇒ Boolean
Test if two items occur at the same time (same start date and equal duration).
-
#search(search, distance: 3, negate: false, case_type: :smart, fuzzy: false) ⇒ Boolean
Test if item matches search string.
- #should_finish? ⇒ Boolean
- #should_time? ⇒ Boolean
-
#tag(tags, **options) ⇒ Object
Add (or remove) tags from the title of the item.
-
#tags ⇒ Array
Get a list of tags on the item.
-
#tags?(tags, bool = :and, negate: false) ⇒ Boolean
Test if item contains tag(s).
-
#to_s ⇒ Object
outputs item in Doing file format, including leading tab.
Constructor Details
#initialize(date, title, section, note = nil) ⇒ Item
Initialize an item with date, title, section, and optional note
23 24 25 26 27 28 |
# File 'lib/doing/item.rb', line 23 def initialize(date, title, section, note = nil) @date = date.is_a?(Time) ? date : Time.parse(date) @title = title @section = section @note = Note.new(note) end |
Instance Attribute Details
#date ⇒ Object
Returns the value of attribute date.
8 9 10 |
# File 'lib/doing/item.rb', line 8 def date @date end |
#id ⇒ String (readonly)
Generate a hash that represents the entry
63 64 65 |
# File 'lib/doing/item.rb', line 63 def id @id end |
#note ⇒ Object
Returns the value of attribute note.
8 9 10 |
# File 'lib/doing/item.rb', line 8 def note @note end |
#section ⇒ Object
Returns the value of attribute section.
8 9 10 |
# File 'lib/doing/item.rb', line 8 def section @section end |
#title ⇒ Object
Returns the value of attribute title.
8 9 10 |
# File 'lib/doing/item.rb', line 8 def title @title end |
Instance Method Details
#duration ⇒ Object
If the entry doesn't have a @done date, return the elapsed time
35 36 37 38 39 |
# File 'lib/doing/item.rb', line 35 def duration return nil if @title =~ /(?<=^| )@done\b/ return Time.now - @date end |
#end_date ⇒ Time
Get the value of the item's @done tag
56 57 58 |
# File 'lib/doing/item.rb', line 56 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 |
#equal?(other) ⇒ Boolean
Test for equality between items
74 75 76 77 78 79 80 81 82 |
# File 'lib/doing/item.rb', line 74 def equal?(other) return false if @title.strip != other.title.strip return false if @date != other.date return false unless @note.equal?(other.note) true end |
#interval ⇒ Object
Get the difference between the item's start date and the value of its @done tag (if present)
47 48 49 |
# File 'lib/doing/item.rb', line 47 def interval @interval ||= calc_interval end |
#move_to(new_section, label: true, log: true) ⇒ Object
Move item from current section to destination section
242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/doing/item.rb', line 242 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.truncate(60)} from #{from} to #{@section}") self end |
#overlapping_time?(item_b) ⇒ Boolean
Test if the interval between start date and @done value overlaps with another item's
103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/doing/item.rb', line 103 def overlapping_time?(item_b) return true if same_time?(item_b) start_a = date interval = interval end_a = interval ? start_a + interval.to_i : start_a start_b = item_b.date interval = item_b.interval end_b = interval ? start_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 |
#same_time?(item_b) ⇒ Boolean
Test if two items occur at the same time (same start date and equal duration)
91 92 93 |
# File 'lib/doing/item.rb', line 91 def same_time?(item_b) date == item_b.date ? interval == item_b.interval : false end |
#search(search, distance: 3, negate: false, case_type: :smart, fuzzy: false) ⇒ Boolean
Test if item matches search string
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/doing/item.rb', line 200 def search(search, distance: 3, negate: false, case_type: :smart, fuzzy: false) text = @title + @note.to_s matches = text =~ search.to_rx(distance: distance, case_type: case_type) # if search.is_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 |
#should_finish? ⇒ Boolean
223 224 225 |
# File 'lib/doing/item.rb', line 223 def should_finish? should?('never_finish') end |
#should_time? ⇒ Boolean
227 228 229 |
# File 'lib/doing/item.rb', line 227 def should_time? should?('never_time') end |
#tag(tags, **options) ⇒ Object
Add (or remove) tags from the title of the item
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 |
# File 'lib/doing/item.rb', line 129 def tag(, **) added = [] removed = [] date = .fetch(:date, false) [:value] ||= date ? Time.now.strftime('%F %R') : nil .delete(:date) single = .fetch(:single, false) .delete(:single) = . if .is_a? ::String remove = .fetch(:remove, false) .each do |tag| bool = remove ? :and : :not if (tag, bool) @title.tag!(tag, **).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 |
#tags ⇒ Array
Get a list of tags on the item
161 162 163 |
# File 'lib/doing/item.rb', line 161 def @title.scan(/(?<= |\A)@([^\s(]+)/).map { |tag| tag[0] }.sort.uniq end |
#tags?(tags, bool = :and, negate: false) ⇒ Boolean
Test if item contains tag(s)
174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/doing/item.rb', line 174 def (, bool = :and, negate: false) = () bool = bool.normalize_bool matches = case bool when :and () when :not () else () end negate ? !matches : matches end |
#to_s ⇒ Object
outputs item in Doing file format, including leading tab
255 256 257 |
# File 'lib/doing/item.rb', line 255 def to_s "\t- #{@date.strftime('%Y-%m-%d %H:%M')} | #{@title}#{@note.empty? ? '' : "\n#{@note}"}" end |