timr 0.1.0.pre.dev.1 → 0.1.0.pre.dev.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b78ed2b17c8e1324c1e8ce4ea8d331955c861227
4
- data.tar.gz: cc2b02d5c1d05dd690ad117e76b5b0cc3e17df1f
3
+ metadata.gz: 4157f4d824d2cadedc511f421b488656ac6a9640
4
+ data.tar.gz: f859883d4ee1a270a61653e4e6c063bacd5f9969
5
5
  SHA512:
6
- metadata.gz: 984d1c45cf0e32ef972ff0f94c427fa792071c5f6520235b97acc35952b151ee2619ca00025ad5da692793e8d6a1eb890d3874e0f21941ac5d5b2f6cc9ae87c0
7
- data.tar.gz: 5bcbacb70f1b9412213d3b7b7214e38c7b081ef2357de42be7594f70e25d7571a36b4e982c80df9d0b18cc7760d1c57a8a7b416eb77d5ad0cda249330ae53ddc
6
+ metadata.gz: 461b4bccfd4fd85530a1d570eb8feac64c4f21e47cb2846e18688bbfe8a053e75934f7444f9fa30bb1cc5983b8f089615e316cecfc2f3cf0114717eda371c5cd
7
+ data.tar.gz: ab112bd2d0e900913dac25283681c2eddf21ae381e78b2299b7d42836baab4e8cd7f4ab6ab2a94685ff22eb9878d4c73116f4c3297622e4a970981ee99cad133
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  /.bundle/
2
2
  .setup
3
+ /bin/dev
3
4
  /releases/
4
5
  README.html
5
6
  /tmp/
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- timr (0.1.0.pre.dev.1)
4
+ timr (0.1.0.pre.dev.5)
5
5
  curses (~> 1.0)
6
6
  thefox-ext (~> 1.4)
7
7
  uuid (~> 2.3)
data/Makefile CHANGED
@@ -6,7 +6,3 @@ include Makefile.common
6
6
 
7
7
  dev:
8
8
  RUBYOPT=-rbundler/setup ruby ./bin/timr
9
-
10
- .PHONY: test
11
- test:
12
- RUBYOPT=-w $(BUNDLER) exec ./tests/ts_all.rb
data/bin/timr CHANGED
@@ -31,8 +31,6 @@ end
31
31
  ARGV << '-h' if ARGV.count == 0
32
32
  opts.parse(ARGV)
33
33
 
34
- puts 'currently under heavy development'
35
-
36
- # timr = TheFox::Timr::Timr.new(@options[:dir])
37
- # timr.run
38
- # timr.close
34
+ timr = TheFox::Timr::Timr.new(@options[:dir])
35
+ timr.run
36
+ timr.close
data/lib/timr.rb CHANGED
@@ -3,6 +3,7 @@ require 'timr/version'
3
3
  require 'timr/timr'
4
4
  require 'timr/stack'
5
5
  require 'timr/task'
6
+ require 'timr/track'
6
7
  require 'timr/window'
7
8
  require 'timr/window_help'
8
9
  require 'timr/window_tasks'
data/lib/timr/stack.rb CHANGED
@@ -34,7 +34,7 @@ module TheFox
34
34
  @tasks.map{ |task|
35
35
  status = task.status
36
36
  status = '*' if task == @task
37
- "#{status} #{task.name}"
37
+ "#{status} #{task}"
38
38
  }
39
39
  end
40
40
 
@@ -63,11 +63,13 @@ module TheFox
63
63
  end
64
64
 
65
65
  def push(task)
66
- @task.stop if has_task?
67
-
68
- @task = task
69
- @task.start
70
- @tasks << @task
66
+ if !@tasks.include?(task)
67
+ @task.stop if has_task?
68
+
69
+ @task = task
70
+ @task.start
71
+ @tasks << @task
72
+ end
71
73
  end
72
74
 
73
75
  end
data/lib/timr/task.rb CHANGED
@@ -1,6 +1,5 @@
1
1
 
2
2
  require 'time'
3
- #require 'yaml'
4
3
  require 'yaml/store'
5
4
  require 'uuid'
6
5
 
@@ -23,8 +22,9 @@ module TheFox
23
22
  'created' => Time.now.strftime(TIME_FORMAT),
24
23
  'modified' => Time.now.strftime(TIME_FORMAT),
25
24
  }
26
- @time = nil
25
+ @track = nil
27
26
  @timeline = []
27
+ @timeline_diff_total = nil
28
28
 
29
29
  @path = path
30
30
  if !@path.nil?
@@ -36,11 +36,8 @@ module TheFox
36
36
  content = YAML::load_file(path)
37
37
  @meta = content['meta']
38
38
  @timeline = content['timeline']
39
- .map{ |time_raw|
40
- time = {
41
- 'b' => Time.parse(time_raw['b']),
42
- 'e' => Time.parse(time_raw['e']),
43
- }
39
+ .map{ |track_raw|
40
+ Track.from_h(self, track_raw)
44
41
  }
45
42
  end
46
43
 
@@ -49,16 +46,8 @@ module TheFox
49
46
  path = File.expand_path("task_#{@meta['id']}.yml", basepath)
50
47
 
51
48
  timeline_c = @timeline
52
- .clone
53
- .map{ |time|
54
- time = time.clone
55
- if !time['b'].nil?
56
- time['b'] = time['b'].strftime(TIME_FORMAT)
57
- end
58
- if !time['e'].nil?
59
- time['e'] = time['e'].strftime(TIME_FORMAT)
60
- end
61
- time
49
+ .map{ |track|
50
+ track.to_h
62
51
  }
63
52
 
64
53
  store = YAML::Store.new(path)
@@ -106,22 +95,25 @@ module TheFox
106
95
  @meta['description'] = description == '' ? nil : description
107
96
  end
108
97
 
98
+ def timeline
99
+ @timeline
100
+ end
101
+
109
102
  def start
110
103
  if !running?
111
104
  changed
112
- @time = {
113
- 'b' => Time.now, # begin
114
- 'e' => nil, # end
115
- }
116
- @timeline << @time
105
+ @track = Track.new(self)
106
+ @timeline << @track
117
107
  end
118
108
  @status = :running
119
109
  end
120
110
 
121
111
  def stop
122
- if running? && !@time.nil?
112
+ if running? && !@track.nil?
123
113
  changed
124
- @time['e'] = Time.now
114
+ @track.end = Time.now
115
+ @track = nil
116
+ @timeline_diff_total = nil
125
117
  end
126
118
  @status = :stop
127
119
  end
@@ -138,6 +130,59 @@ module TheFox
138
130
  name
139
131
  end
140
132
 
133
+ def to_list_s
134
+ name
135
+ end
136
+
137
+ def run_time_track
138
+ hours = 0
139
+ minutes = 0
140
+ seconds = 0
141
+
142
+ if !@track.nil?
143
+ diff = (Time.now - @track.begin).to_i.abs
144
+ hours = diff / 3600
145
+
146
+ diff -= hours * 3600
147
+ minutes = diff / 60
148
+
149
+ diff -= minutes * 60
150
+ seconds = diff
151
+ end
152
+
153
+ [hours, minutes, seconds]
154
+ end
155
+
156
+ def run_time_total
157
+ # Cache all other tracks.
158
+ if @timeline_diff_total.nil?
159
+ @timeline_diff_total = @timeline
160
+ .select{ |track| track != @track }
161
+ .map{ |track| track.diff }
162
+ .inject(:+)
163
+ end
164
+
165
+ hours = 0
166
+ minutes = 0
167
+ seconds = 0
168
+
169
+ track_diff = 0
170
+ if !@track.nil?
171
+ track_diff = (Time.now - @track.begin).to_i.abs
172
+ end
173
+
174
+ diff = @timeline_diff_total.to_i + track_diff
175
+ hours = diff / 3600
176
+
177
+ diff -= hours * 3600
178
+ minutes = diff / 60
179
+
180
+ diff -= minutes * 60
181
+ seconds = diff
182
+
183
+ [hours, minutes, seconds]
184
+ end
185
+
141
186
  end
142
187
 
143
188
  end
data/lib/timr/timr.rb CHANGED
@@ -1,6 +1,7 @@
1
1
 
2
2
  require 'curses'
3
3
  require 'time'
4
+ require 'fileutils'
4
5
 
5
6
  module TheFox
6
7
  module Timr
@@ -25,27 +26,29 @@ module TheFox
25
26
  tasks_load
26
27
 
27
28
  @window = nil
28
- @window_timeline = TimelineWindow.new
29
29
  @window_help = HelpWindow.new
30
30
  @window_test = TestWindow.new
31
31
 
32
32
  @window_tasks = TasksWindow.new
33
33
  @window_tasks.tasks = @tasks
34
+
35
+ @window_timeline = TimelineWindow.new
36
+ @window_timeline.tasks = @tasks
34
37
  end
35
38
 
36
39
  def init_dirs
37
40
  if !Dir.exist?(@base_dir_path)
38
- Dir.mkdir(@base_dir_path)
41
+ FileUtils.mkdir_p(@base_dir_path)
39
42
  end
40
43
  if !Dir.exist?(@data_dir_path)
41
- Dir.mkdir(@data_dir_path)
44
+ FileUtils.mkdir_p(@data_dir_path)
42
45
  end
43
46
  end
44
47
 
45
48
  def tasks_load
46
49
  Dir.chdir(@data_dir_path) do
47
50
  Dir['task_*.yml'].each do |file_name|
48
- puts "file: '#{file_name}'"
51
+ #puts "file: '#{file_name}'"
49
52
  task = Task.new(file_name)
50
53
  @tasks[task.id] = task
51
54
  end
@@ -66,7 +69,7 @@ module TheFox
66
69
  end
67
70
  end
68
71
 
69
- def init_curses
72
+ def ui_init_curses
70
73
  Curses.noecho
71
74
  Curses.timeout = TIMEOUT
72
75
  Curses.curs_set(0)
@@ -81,7 +84,7 @@ module TheFox
81
84
  Curses.init_pair(Curses::COLOR_YELLOW, Curses::COLOR_BLACK, Curses::COLOR_YELLOW)
82
85
  end
83
86
 
84
- def title_line
87
+ def ui_title_line
85
88
  title = "#{NAME} #{VERSION} -- #{@base_dir_name}"
86
89
  if Curses.cols <= title.length + 1
87
90
  title = "#{NAME} #{VERSION}"
@@ -97,7 +100,7 @@ module TheFox
97
100
  end
98
101
  end
99
102
 
100
- def status_text(text, attrn = Curses::A_NORMAL)
103
+ def ui_status_text(text, attrn = Curses::A_NORMAL)
101
104
  line_nr = Curses.lines - 1
102
105
 
103
106
  Curses.setpos(line_nr, 0)
@@ -109,12 +112,16 @@ module TheFox
109
112
  Curses.refresh
110
113
  end
111
114
 
112
- def status_input(text)
115
+ def ui_status_text_error(text)
116
+ ui_status_text(text, Curses.color_pair(Curses::COLOR_RED) | Curses::A_BOLD)
117
+ end
118
+
119
+ def ui_status_input(text)
113
120
  Curses.echo
114
121
  Curses.timeout = -1
115
122
  Curses.curs_set(1)
116
123
 
117
- status_text(text)
124
+ ui_status_text(text)
118
125
 
119
126
  input = ''
120
127
  abort = false
@@ -144,7 +151,7 @@ module TheFox
144
151
  input
145
152
  end
146
153
 
147
- def status_line(init = false)
154
+ def ui_status_line(init = false)
148
155
  line_nr = Curses.lines - 2
149
156
 
150
157
  Curses.attron(Curses.color_pair(Curses::COLOR_YELLOW) | Curses::A_NORMAL) do
@@ -156,9 +163,13 @@ module TheFox
156
163
 
157
164
  Curses.setpos(line_nr, COL)
158
165
  if @stack.has_task?
159
- Curses.addstr(@stack.task.status)
166
+ status = @stack.task.status
167
+ run_time_track = '%4d:%02d:%02d' % @stack.task.run_time_track
168
+ run_time_total = '%4d:%02d:%02d' % @stack.task.run_time_total
169
+
170
+ Curses.addstr("#{status} #{run_time_track} #{run_time_total}")
160
171
  else
161
- Curses.addstr(TASK_NO_TASK_LOADED_C)
172
+ Curses.addstr("#{TASK_NO_TASK_LOADED_C} ----:--:-- ----:--:--")
162
173
  end
163
174
 
164
175
  if Curses.cols > MIN_COLS
@@ -183,13 +194,13 @@ module TheFox
183
194
  Curses.refresh
184
195
  end
185
196
 
186
- def window_show(window)
197
+ def ui_window_show(window)
187
198
  @window = window
188
- window_refresh
199
+ ui_window_refresh
189
200
  end
190
201
 
191
- def window_refresh
192
- max_lines = content_length
202
+ def ui_window_refresh
203
+ max_lines = ui_content_length
193
204
  (1..max_lines).each do |line_nr|
194
205
  Curses.setpos(line_nr, 0)
195
206
  Curses.clrtoeol
@@ -198,14 +209,18 @@ module TheFox
198
209
  if !@window.nil?
199
210
  line_nr = 1
200
211
  @window.content_refresh
201
- page_length = @window.page_length
202
212
  current_line = @window.current_line
203
213
  max_line_len = Curses.cols - 2
204
214
  @window.page.each do |line_object|
205
215
  is_cursor = line_nr == @window.cursor
206
216
 
207
- line_text = line_object.to_s
208
- #line_text = "#{line_text} #{is_cursor ? 'X' : ''}"
217
+ line_text = ''
218
+ if line_object.is_a?(Task) || line_object.is_a?(Track)
219
+ line_text = line_object.to_list_s
220
+ else
221
+ line_text = line_object.to_s
222
+ end
223
+
209
224
  if line_text.length > max_line_len
210
225
  cut = line_text.length - max_line_len + 4
211
226
  line_text = "#{line_text[0..-cut]}..."
@@ -213,16 +228,22 @@ module TheFox
213
228
 
214
229
  rest = Curses.cols - line_text.length - COL
215
230
 
216
- if is_cursor
217
- Curses.setpos(line_nr, 0)
218
- Curses.attron(Curses.color_pair(Curses::COLOR_BLUE) | Curses::A_BOLD) do
219
- Curses.addstr(' ' * COL + line_text + ' ' * rest)
231
+ if @window.has_cursor?
232
+ if is_cursor
233
+ Curses.setpos(line_nr, 0)
234
+ Curses.attron(Curses.color_pair(Curses::COLOR_BLUE) | Curses::A_BOLD) do
235
+ Curses.addstr(' ' * COL + line_text + ' ' * rest)
236
+ end
237
+ else
238
+ Curses.setpos(line_nr, COL)
239
+ Curses.addstr(line_text)
220
240
  end
221
241
  else
222
242
  Curses.setpos(line_nr, COL)
223
243
  Curses.addstr(line_text)
224
244
  end
225
245
 
246
+
226
247
  line_nr += 1
227
248
  end
228
249
  end
@@ -230,28 +251,32 @@ module TheFox
230
251
  Curses.refresh
231
252
  end
232
253
 
233
- def content_length
254
+ def ui_content_length
234
255
  Curses.lines - RESERVED_LINES - @stack.length
235
256
  end
236
257
 
237
258
  def update_content_length
238
- cl = content_length
259
+ cl = ui_content_length
239
260
 
240
- @window_timeline.content_length = cl
241
261
  @window_help.content_length = cl
242
262
  @window_test.content_length = cl
243
263
  @window_tasks.content_length = cl
264
+ @window_timeline.content_length = cl
265
+ end
266
+
267
+ def ui_refresh
268
+ ui_stack_lines_refresh
269
+ ui_window_refresh
244
270
  end
245
271
 
246
- def refresh
272
+ def ui_refresh_all
247
273
  update_content_length
248
- title_line
249
- status_line(true)
250
- stack_lines
251
- window_refresh
274
+ ui_title_line
275
+ ui_status_line(true)
276
+ ui_refresh
252
277
  end
253
278
 
254
- def stack_lines
279
+ def ui_stack_lines_refresh
255
280
  line_nr = Curses.lines - (3 + (@stack.length - 1))
256
281
 
257
282
  Curses.attron(Curses.color_pair(Curses::COLOR_BLUE)) do
@@ -269,11 +294,46 @@ module TheFox
269
294
  Curses.refresh
270
295
  end
271
296
 
297
+ def task_apply(task = nil, push = false)
298
+ if task.nil?
299
+ @stack.pop_all
300
+ else
301
+ @tasks[task.id] = task
302
+ if push
303
+ @stack.push(task)
304
+ else
305
+ @stack.pop_all(task)
306
+ end
307
+ end
308
+
309
+ window_content_changed
310
+ ui_stack_lines_refresh
311
+ ui_window_refresh if !push
312
+ end
313
+
314
+ def task_apply_replace_stack(task)
315
+ task_apply(task, false)
316
+ end
317
+
318
+ def task_apply_stack_pop_all
319
+ task_apply(nil, false)
320
+ end
321
+
322
+ def task_apply_push(task)
323
+ task_apply(task, true)
324
+ end
325
+
326
+ def window_content_changed
327
+ @window_tasks.content_changed
328
+ @window_timeline.content_changed
329
+ end
330
+
272
331
  def run
273
- init_curses
332
+ ui_init_curses
274
333
  update_content_length
275
- title_line
276
- status_line(true)
334
+ ui_title_line
335
+ ui_status_line(true)
336
+ ui_window_show(@window_timeline)
277
337
 
278
338
  loop do
279
339
  key_pressed = Curses.getch
@@ -281,96 +341,113 @@ module TheFox
281
341
  case key_pressed
282
342
  when Curses::Key::NPAGE
283
343
  @window.next_page if !@window.nil?
284
- window_refresh
344
+ ui_window_refresh
285
345
  when Curses::Key::PPAGE
286
346
  @window.previous_page if !@window.nil?
287
- window_refresh
347
+ ui_window_refresh
288
348
  when Curses::Key::DOWN
289
- #@window.next_line if !@window.nil?
290
- @window.cursor_next_line if !@window.nil?
291
- #status_text("Cursor: #{@window.cursor} c=#{content_length} l=#{@window.current_line} pr=#{@window.page_refreshes} cr=#{@window.content_refreshes}") if !@window.nil?
292
- window_refresh
349
+ if !@window.nil? && @window.has_cursor?
350
+ @window.cursor_next_line
351
+
352
+ #ui_status_text("Cursor: #{@window.cursor} c=#{ui_content_length} l=#{@window.current_line} pr=#{@window.page_refreshes} cr=#{@window.content_refreshes}")
353
+
354
+ ui_window_refresh
355
+ end
293
356
  when Curses::Key::UP
294
- #@window.previous_line if !@window.nil?
295
- @window.cursor_previous_line if !@window.nil?
296
- #status_text("Cursor: #{@window.cursor} c=#{content_length} l=#{@window.current_line} pr=#{@window.page_refreshes} cr=#{@window.content_refreshes}") if !@window.nil?
297
- window_refresh
357
+ if !@window.nil? && @window.has_cursor?
358
+ @window.cursor_previous_line
359
+
360
+ #ui_status_text("Cursor: #{@window.cursor} c=#{ui_content_length} l=#{@window.current_line} pr=#{@window.page_refreshes} cr=#{@window.content_refreshes}")
361
+
362
+ ui_window_refresh
363
+ end
298
364
  when Curses::Key::HOME
299
365
  @window.first_page if !@window.nil?
300
- window_refresh
366
+ ui_window_refresh
301
367
  when Curses::Key::END
302
368
  @window.last_page if !@window.nil?
303
- window_refresh
369
+ ui_window_refresh
304
370
  when Curses::Key::RESIZE
305
371
  update_content_length
306
- status_text("Resizing: #{Curses.lines}x#{Curses.cols}")
372
+ ui_status_text("Resizing: #{Curses.lines}x#{Curses.cols}")
307
373
 
308
374
  # Refreshing the complete screen while resizing
309
375
  # can make everything slower. So for fast resizing
310
376
  # comment this line.
311
- refresh
377
+ ui_refresh_all
312
378
  when 10
313
379
  object = @window.page_object if !@window.nil?
380
+
381
+ task = nil
382
+ if object.is_a?(Task)
383
+ task = object
384
+ elsif object.is_a?(Track)
385
+ task = object.task
386
+ end
387
+
388
+ if task.nil?
389
+ ui_status_text("Unrecognized object: #{object.class}")
390
+ else
391
+ task_apply_replace_stack(task)
392
+ end
393
+ when 'b', 'p'
394
+ object = @window.page_object if !@window.nil?
395
+
396
+ task = nil
314
397
  if object.is_a?(Task)
315
- status_text("Object: #{object.class} #{object}")
398
+ task = object
399
+ elsif object.is_a?(Track)
400
+ task = object.task
401
+ end
402
+
403
+ if task.nil?
404
+ ui_status_text("Unrecognized object: #{object.class}")
405
+ else
406
+ task_apply_push(task)
316
407
  end
317
408
  when 'r'
318
- refresh
319
- status_text('')
409
+ ui_refresh_all
410
+ ui_status_text('')
320
411
  when 'n'
321
- task_name = status_input('New task: ')
412
+ task_name = ui_status_input('New task: ')
322
413
  if task_name.nil?
323
- status_text('Aborted.')
414
+ ui_status_text('Aborted.')
324
415
  else
325
- task_description = status_input('Description: ')
416
+ task_description = ui_status_input('Description: ')
326
417
 
327
418
  task = @stack.create(task_name, task_description)
328
- @tasks[task.id] = task
329
- @stack.pop_all(task)
330
- @window_tasks.content_changed
419
+ task_apply_replace_stack(task)
331
420
 
332
- status_text("Task '#{task_name}' created: #{task.id}")
333
-
334
- stack_lines
335
- window_refresh
421
+ ui_status_text("Task '#{task_name}' created: #{task.id}")
336
422
  end
337
- when 'p'
338
- task = Task.new
339
- task.name = "task #{Time.now.strftime(TIME_FORMAT)}"
340
- task.description = 'description1'
341
-
342
- @tasks[task.id] = task
343
- @stack.push(task)
344
-
345
- status_text("Task '#{task_name}' created: #{task.id}")
346
-
347
- stack_lines
348
423
  when 'x'
349
424
  @stack.task.stop if @stack.has_task?
350
425
  when 'c'
351
426
  @stack.task.toggle if @stack.has_task?
352
427
  when 'v'
353
428
  if @stack.pop
354
- stack_lines
355
- window_refresh
429
+ window_content_changed
430
+ ui_refresh
356
431
  end
432
+ when 'f'
433
+ task_apply_stack_pop_all
357
434
  when 'h', '?'
358
- window_show(@window_help)
435
+ ui_window_show(@window_help)
359
436
  when 't' # Test Windows
360
- window_show(@window_test)
437
+ ui_window_show(@window_test)
361
438
  when '1'
362
- window_show(@window_timeline)
439
+ ui_window_show(@window_timeline)
363
440
  when '2'
364
- window_show(@window_tasks)
441
+ ui_window_show(@window_tasks)
365
442
  when 'w'
366
443
  tasks_save
367
444
  when 'q'
368
445
  break
369
446
  when nil
370
447
  # Do some work.
371
- status_line
448
+ ui_status_line
372
449
  else
373
- status_text("Invalid key '#{key_pressed}' (#{Curses.keyname(key_pressed)})", Curses.color_pair(Curses::COLOR_RED) | Curses::A_BOLD)
450
+ ui_status_text_error("Invalid key '#{key_pressed}' (#{Curses.keyname(key_pressed)})")
374
451
  end
375
452
  end
376
453
  end
data/lib/timr/track.rb ADDED
@@ -0,0 +1,84 @@
1
+
2
+ require 'time'
3
+ require 'thefox-ext'
4
+
5
+ module TheFox
6
+ module Timr
7
+
8
+ class Track
9
+
10
+ def initialize(task, tbegin = Time.now, tend = nil)
11
+ @task = task
12
+ @tbegin = tbegin
13
+ @tend = tend
14
+ end
15
+
16
+ def begin=(tb)
17
+ @tbegin = tb
18
+ end
19
+
20
+ def begin
21
+ @tbegin
22
+ end
23
+
24
+ def end=(te)
25
+ @tend = te
26
+ end
27
+
28
+ def end
29
+ @tend
30
+ end
31
+
32
+ def diff
33
+ if !@tbegin.nil? && !@tend.nil?
34
+ (@tend - @tbegin).abs
35
+ else
36
+ 0
37
+ end
38
+ end
39
+
40
+ def task
41
+ @task
42
+ end
43
+
44
+ def to_h
45
+ h = {}
46
+ h['b'] = @tbegin.strftime(TIME_FORMAT) if !@tbegin.nil?
47
+ h['e'] = @tend.strftime(TIME_FORMAT) if !@tend.nil?
48
+ h
49
+ end
50
+
51
+ def to_s
52
+ 'track'
53
+ end
54
+
55
+ def to_list_s
56
+ tend_date = nil
57
+ tend_time_s = ''
58
+ if !@tend.nil?
59
+ tend_time_s = !@tend.nil? ? @tend.strftime('%R') : 'xx:xx'
60
+ tend_date = @tend.to_date
61
+ end
62
+
63
+ tbegin_date_s = ''
64
+ tbegin_date = @tbegin.to_date
65
+ tend_date_s = ''
66
+ if (tbegin_date != tend_date && !tend_date.nil?) || !tbegin_date.today?
67
+ tbegin_date_s = @tbegin.strftime('%F')
68
+ tend_date_s = @tend.strftime('%F') if !@tend.nil?
69
+ end
70
+
71
+ '%10s %5s - %5s %10s %s' % [tbegin_date_s, @tbegin.strftime('%R'), tend_time_s, tend_date_s, @task.to_list_s]
72
+ end
73
+
74
+ def self.from_h(task, h)
75
+ t = Track.new(task)
76
+ t.begin = Time.parse(h['b'])
77
+ t.end = Time.parse(h['e'])
78
+ t
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
data/lib/timr/version.rb CHANGED
@@ -2,8 +2,8 @@
2
2
  module TheFox
3
3
  module Timr
4
4
  NAME = 'Timr'
5
- VERSION = '0.1.0-dev.1'
6
- DATE = '2016-05-08'
5
+ VERSION = '0.1.0-dev.5'
6
+ DATE = '2016-05-10'
7
7
  HOMEPAGE = 'https://github.com/TheFox/timr'
8
8
 
9
9
  COL = 1
data/lib/timr/window.rb CHANGED
@@ -8,15 +8,21 @@ module TheFox
8
8
  @content_length = 0
9
9
  @current_line = 0
10
10
  @cursor = 1
11
+ @has_cursor = false
11
12
  @content_changed = true
12
13
  @content_refreshes = 1
13
- @page = nil
14
+ @page = []
14
15
  @page_changed = true
15
16
  @page_refreshes = 1
16
17
 
18
+ setup
17
19
  content_refresh
18
20
  end
19
21
 
22
+ def setup
23
+
24
+ end
25
+
20
26
  def content_length=(content_length)
21
27
  @content_length = content_length
22
28
  end
@@ -50,16 +56,13 @@ module TheFox
50
56
  end
51
57
 
52
58
  def page
53
- if @content.nil?
54
- []
55
- else
56
- if @page.nil? || @page_changed
57
- @page = @content[@current_line, @content_length]
58
- @page_refreshes += 1
59
- @page_changed = false
60
- end
61
- @page
59
+ if @page_changed
60
+ @page = @content[@current_line, @content_length]
61
+ @page_refreshes += 1
62
+ @page_changed = false
62
63
  end
64
+
65
+ @page
63
66
  end
64
67
 
65
68
  def page_object
@@ -67,7 +70,12 @@ module TheFox
67
70
  end
68
71
 
69
72
  def page_length
70
- page.length
73
+ cpage = page
74
+ if cpage.nil?
75
+ 0
76
+ else
77
+ cpage.length
78
+ end
71
79
  end
72
80
 
73
81
  def next_page?
@@ -97,10 +105,10 @@ module TheFox
97
105
  @current_line > 0
98
106
  end
99
107
 
100
- def previous_page
108
+ def previous_page(length = @content_length)
101
109
  if previous_page?
102
110
  page_changed
103
- @current_line -= @content_length
111
+ @current_line -= length
104
112
  if @current_line < 0
105
113
  @current_line = 0
106
114
  end
@@ -118,8 +126,14 @@ module TheFox
118
126
  end
119
127
 
120
128
  def last_page
121
- page_changed
122
- @current_line = @content.length - @content_length
129
+ if !last_page?
130
+ page_changed
131
+
132
+ new_current_line = @content.length - @content_length
133
+ if new_current_line >= 0
134
+ @current_line = @content.length - @content_length
135
+ end
136
+ end
123
137
  cursor_last_line
124
138
  end
125
139
 
@@ -141,6 +155,10 @@ module TheFox
141
155
  @cursor
142
156
  end
143
157
 
158
+ def has_cursor?
159
+ @has_cursor
160
+ end
161
+
144
162
  def cursor_next_line
145
163
  @cursor += 1
146
164
  border = @content_length - 2
@@ -183,6 +201,9 @@ module TheFox
183
201
 
184
202
  def cursor_last_line
185
203
  @cursor = @content_length
204
+ if page_length < @content_length
205
+ @cursor = page_length
206
+ end
186
207
  end
187
208
 
188
209
  def cursor_first_line
@@ -12,12 +12,15 @@ module TheFox
12
12
  ' c .. Current Task: Start/Continue',
13
13
  ' x .. Current Task: Stop',
14
14
  ' v .. Current Task: Stop and Pop from Stack',
15
+ ' f .. Stop and deselect all Tasks on the Stack',
16
+ ' p, b .. Push and start selected Task.',
15
17
  ' r .. Refresh Window',
16
18
  ' w .. Write all changes.',
17
19
  ' q .. Exit',
18
20
  ' h .. Help',
19
21
  ' 1 .. Timeline Window',
20
22
  ' 2 .. Tasks Window',
23
+ ' RETURN .. Start selected task.',
21
24
  ' KEY UP .. Move Cursor up.',
22
25
  ' KEY DOWN .. Move Cursor down.',
23
26
  '',
@@ -15,6 +15,7 @@ module TheFox
15
15
 
16
16
  def content
17
17
  if @tasks.nil? || @tasks.length == 0
18
+ @has_cursor = false
18
19
  [
19
20
  '',
20
21
  '#### NO TASKS YET ####',
@@ -22,9 +23,10 @@ module TheFox
22
23
  "Press 'n' to create a new task.",
23
24
  ]
24
25
  else
26
+ @has_cursor = true
25
27
  @tasks
26
28
  .sort_by{ |k, v|
27
- v.name
29
+ v.name.downcase
28
30
  }
29
31
  .map{ |a| a[1] }
30
32
  end
@@ -4,6 +4,10 @@ module TheFox
4
4
 
5
5
  class TestWindow < Window
6
6
 
7
+ def setup
8
+ @has_cursor = true
9
+ end
10
+
7
11
  def content
8
12
  c = []
9
13
  (1..30).each do |n|
@@ -4,8 +4,33 @@ module TheFox
4
4
 
5
5
  class TimelineWindow < Window
6
6
 
7
+ @tasks = nil
8
+
9
+ def tasks=(tasks)
10
+ content_changed
11
+ @tasks = tasks
12
+ end
13
+
7
14
  def content
8
-
15
+ if @tasks.nil? || @tasks.length == 0
16
+ @has_cursor = false
17
+ [
18
+ '',
19
+ '#### NO TASKS YET ####',
20
+ '',
21
+ "Press 'n' to create a new task.",
22
+ ]
23
+ else
24
+ @has_cursor = true
25
+ @tasks
26
+ .map{ |task_id, task|
27
+ task.timeline
28
+ }
29
+ .flatten
30
+ .sort{ |task_a, task_b|
31
+ task_a.begin <=> task_b.begin || task_a.end <=> task_b.end
32
+ }
33
+ end
9
34
  end
10
35
 
11
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre.dev.1
4
+ version: 0.1.0.pre.dev.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Mayer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-08 00:00:00.000000000 Z
11
+ date: 2016-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -80,12 +80,12 @@ files:
80
80
  - Makefile
81
81
  - Makefile.common
82
82
  - README.md
83
- - bin/dev
84
83
  - bin/timr
85
84
  - lib/timr.rb
86
85
  - lib/timr/stack.rb
87
86
  - lib/timr/task.rb
88
87
  - lib/timr/timr.rb
88
+ - lib/timr/track.rb
89
89
  - lib/timr/version.rb
90
90
  - lib/timr/window.rb
91
91
  - lib/timr/window_help.rb
data/bin/dev DELETED
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # coding: UTF-8
3
-
4
- require 'pp'
5
- require 'timr'
6
-
7
-
8
- h = {
9
- #'x' => 10,
10
- #'y' => 5,
11
- }
12
-
13
- pp h.length