Class: Journal

Inherits:
Object
  • Object
show all
Defined in:
lib/rodo/rodolib.rb

Overview

Journal is the datastore class for the todo list managed by rodolib.

Responsible for:

- Parsing a md file into a rodolib Journal
- Serialization into a md file
- Splitting into days

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#daysObject

Returns the value of attribute days.



37
38
39
# File 'lib/rodo/rodolib.rb', line 37

def days
  @days
end

Class Method Details

.from_s(s) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/rodo/rodolib.rb', line 38

def self.from_s(s)

  j = Journal.new
  j.days = []

  next_day = []
  s.each_line { |line|
    if line =~ /^\s*\#\s*(\d\d\d\d-\d\d-\d\d)/ && next_day.size > 0
      j.days << TodoDay.new(next_day)
      next_day = []
    end
    next_day << line.rstrip if next_day.size > 0 || line.strip.length > 0 # Skip leading empty lines
  }
  if (next_day.size > 0 && next_day.any? { |line| line.strip.length > 0 })
    j.days << TodoDay.new(next_day)
  end

  return j
end

Instance Method Details

#close(day) ⇒ Object

Postpones all unfinished todos to today’s date Returns the index of the target date to which things were postponed



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
# File 'lib/rodo/rodolib.rb', line 142

def close(day)

  unfinished_lines = [nil] * day.lines.size

  day.lines.each_with_index { |line, index|
    if line =~ /^\s*(-\s+)?\[(.)\]/

      if $2 == " "
        # Copy all unfinished tasks and...
        unfinished_lines[index] = line.dup

        # ...their parent entries (recursively)
        parent_index = index
        while (parent_index = day.parent_index(parent_index)) != nil
          unfinished_lines[parent_index] ||= day.lines[parent_index].dup
        end
        line.sub!(/\[\s\]/, "[>]")
      end

    # Copy top level structure:
    elsif !(line =~ /^\s*[-*]\s+/ || line =~ /^\s*#\s/)
      unfinished_lines[index] = line.dup
    end
  }

  if unfinished_lines[0] =~ /^\s*\#\s*(\d\d\d\d-\d\d-\d\d)/
    unfinished_lines.shift
  end

  target_day = ensure_day(Date.today)
  if target_day == day
    # When closing on the same day: append hour and minutes
    newDate = "# #{Time.now.strftime("%Y-%m-%d %a %H:%M")}"
    target_day = TodoDay.new([newDate])
    insertion_index = days.index { |d| target_day.date >= d.date } || 0
    days.insert(insertion_index, target_day)
  end

  # Only append non-empty lines
  unfinished_lines.select! { |l| l != nil }

  target_day.merge_lines(unfinished_lines)

  return days.find_index(target_day)
end

#ensure_day(target_date) ⇒ Object

Returns the TodoDay for the given date creating it if it doesn’t exist



63
64
65
66
67
68
69
70
# File 'lib/rodo/rodolib.rb', line 63

def ensure_day(target_date)
  index = days.find_index { |x| x.date <= target_date } || -1

  if index < 0 || days[index].date != target_date
    days.insert(index, TodoDay.new(["# #{target_date.strftime("%Y-%m-%d")}"]))
  end
  return days[index]
end

#most_recent_indexObject



188
189
190
191
# File 'lib/rodo/rodolib.rb', line 188

def most_recent_index
  today = Date.today
  return days.find_index { |x| x.date <= today } || 0
end

#postpone_day(day, number_of_days_to_postpone = 1) ⇒ Object

Returns the day, number of days in the future from the given day, but at never before today



73
74
75
76
77
78
79
80
81
82
83
# File 'lib/rodo/rodolib.rb', line 73

def postpone_day(day, number_of_days_to_postpone=1)

  number_of_days_to_postpone = 1 if number_of_days_to_postpone < 1

  target_date = (day.date || Date.today).next_day(number_of_days_to_postpone)

  # target_date shouldn't be in the past
  target_date = Date.today if target_date.to_date < Date.today

  return ensure_day(target_date)
end

#postpone_line(day, line_index, number_of_days_to_postpone = 1) ⇒ Object

Postpone the given line on the given day by the given number of days, default=1

Returns false, if there is no todo which can be postponed on the given line Returns the target date to which the line was moved if successful.



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/rodo/rodolib.rb', line 89

def postpone_line(day, line_index, number_of_days_to_postpone=1)

  line = day.lines[line_index]

  # Postpone only works for todos
  return false if !(line =~ /^\s*(-\s+)?\[(.)\]/)

  # Postpone only works for unfinished todos
  return false if $2 != " "

  # First create the target day
  target_day = postpone_day(day, number_of_days_to_postpone)

  # Determine all affected lines
  unfinished_lines = [nil] * day.lines.size

  # Copy all unfinished tasks and...
  unfinished_lines[line_index] = line.dup

  # ...their parent entries (recursively)
  parent_index = line_index
  while (parent_index = day.parent_index(parent_index)) != nil
    unfinished_lines[parent_index] ||= day.lines[parent_index].dup
  end

  # Copy up to 1 whitespace line preceeding
  unfinished_lines.each_with_index { |e, i|
    if e != nil && i != 0 && day.indent_depth(i - 1) == nil
      unfinished_lines[i-1] = ""
    end
  }

  # ...and the children as well!
  # TODO

  # Mark line itself as postponed
  line.sub!(/\[\s\]/, "[>]")

  # Get rid of primary header
  if unfinished_lines[0] =~ /^\s*\#\s*(\d\d\d\d-\d\d-\d\d)/
    unfinished_lines.shift
  end

  # Only append non-empty lines
  unfinished_lines.select! { |l| l != nil }

  target_day.merge_lines(unfinished_lines)

  return target_day
end

#to_sObject



58
59
60
# File 'lib/rodo/rodolib.rb', line 58

def to_s
  days.map { |day| day.to_s }.join("\n\n") + (days.empty? ? "" : "\n")
end