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

Sign up to get free protection for your applications and to get access to all the features.
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