syc-task 0.0.4 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +182 -5
- data/bin/syctask +112 -10
- data/lib/sycstring/string_util.rb +26 -0
- data/lib/syctask.rb +2 -0
- data/lib/syctask/environment.rb +5 -0
- data/lib/syctask/meeting.rb +7 -1
- data/lib/syctask/schedule.rb +7 -2
- data/lib/syctask/task.rb +25 -12
- data/lib/syctask/task_planner.rb +85 -3
- data/lib/syctask/task_scheduler.rb +1 -0
- data/lib/syctask/task_service.rb +3 -1
- data/lib/syctask/task_tracker.rb +159 -0
- data/lib/syctask/times.rb +6 -0
- data/lib/syctask/version.rb +1 -1
- data/lib/syctime/time_util.rb +26 -0
- data/lib/sycutil/console.rb +1 -1
- metadata +121 -42
data/README.rdoc
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
= Simple task organizer
|
2
|
-
|
2
|
+
syctask can be used to create, plan, prioritize and schedule tasks.
|
3
3
|
|
4
4
|
==Install
|
5
5
|
The application can be installed with
|
6
6
|
$ gem install syc-task
|
7
7
|
|
8
8
|
== Usage
|
9
|
-
syctask provides basic task organizer functions as create, update, list
|
9
|
+
syctask provides basic task organizer functions as create, update, list and complete a task. Additional functions are to plan tasks you want to accomplish today. If you are not sure in which sequence to conduct the task you can prioritize them with a pair wise comparisson. You can time tasks with start and stop and you can finally extract tasks from a minutes of meetings file. The schedule task will print a graphical timeline of the working day assigning the planned tasks to the timeline. Busy times are marked red. Meetings are listed with associated tasks that are assigned to the meetings.
|
10
10
|
|
11
11
|
===Create tasks with new
|
12
12
|
Create a new task in the default task directory ~/.tasks
|
@@ -23,7 +23,7 @@ Set a proirity for a task
|
|
23
23
|
|
24
24
|
Prompt for task input
|
25
25
|
$ syctask new
|
26
|
-
will prompt for task titles.
|
26
|
+
will prompt for task titles. Ctrl-D will end input.
|
27
27
|
|
28
28
|
Except for --description you can also provide short forms for the options.
|
29
29
|
|
@@ -44,6 +44,32 @@ Invoke plan with a filter
|
|
44
44
|
1 - My first task
|
45
45
|
(a)dd, (c)omplete, (s)kip, (q)uit?
|
46
46
|
|
47
|
+
===Prioritize tasks
|
48
|
+
Planned tasks can be prioritized in a pair wise comparisson. So each task is
|
49
|
+
compared to all other tasks. The task with the highest priority will bubble on
|
50
|
+
top followed by the task with the next highest priority and so on.
|
51
|
+
|
52
|
+
$ syctask prio
|
53
|
+
1: My first task
|
54
|
+
2: My second task
|
55
|
+
Task 1 has (h)igher or (l)ower priority, or (q)uit: h
|
56
|
+
1: My first task
|
57
|
+
2: My third task
|
58
|
+
Task 1 has (h)igher or (l)ower priority, or (q)uit: l
|
59
|
+
1: My third task
|
60
|
+
2: My fourth task
|
61
|
+
Task 1 has (h)igher or (l)ower priority, or (q)uit: h
|
62
|
+
...
|
63
|
+
|
64
|
+
syctask schedule will then print tasks as follows
|
65
|
+
Tasks
|
66
|
+
-----
|
67
|
+
0: 10 - My fourth task
|
68
|
+
1: 7 - My third task
|
69
|
+
2: 3 - My first task
|
70
|
+
3: 9 - My second task
|
71
|
+
...
|
72
|
+
|
47
73
|
===Create schedule
|
48
74
|
The schedule command will print a graphical schedule with assigning the tasks
|
49
75
|
added with plan.
|
@@ -109,17 +135,168 @@ Update task with ID 1 and provide some informative note
|
|
109
135
|
Complete the task with ID 1 and provide a final note
|
110
136
|
$ syctask done 1 --note "Finalize my first task"
|
111
137
|
|
138
|
+
===Delete tasks
|
139
|
+
Delete tasks with ID 1,3 and 5 from the default task directory
|
140
|
+
$ syctask delete --id 1,3,5
|
141
|
+
|
142
|
+
Delete tasks with ID 8 and 12 from the planned tasks of today. The tasks are
|
143
|
+
only removed from the planned tasks and not physically deleted.
|
144
|
+
$ syctask delete --plan today --id 8,12
|
145
|
+
|
146
|
+
===Task directory and project directory
|
147
|
+
The global options --taskdir and --project determine where the command finds
|
148
|
+
or creates the tasks. The default task directory is ~/.tasks, so if no task
|
149
|
+
directory is specified all commands obtain tasks from or create tasks in
|
150
|
+
~/.tasks. If a project is specified the tasks will be saved to or obtained from the task directories subdirectory specified with the --project flag.
|
151
|
+
|
152
|
+
--taskdir --project Tasks in
|
153
|
+
- - default_task_dir
|
154
|
+
x - task_dir
|
155
|
+
- x default_task_dir/project
|
156
|
+
x x task_dir/project
|
157
|
+
|
158
|
+
In the table the relation of commands to --taskdir and --project are listed.
|
159
|
+
|
160
|
+
Command --taskdir --project Comment
|
161
|
+
delete x x deletes the tasks in taskdir/project
|
162
|
+
done x x marks tasks in taskdir/project as done
|
163
|
+
help - -
|
164
|
+
list x x lists tasks in taskdir/project
|
165
|
+
new x x creates tasks in taskdir/project
|
166
|
+
plan x x retrieves tasks to plan from taskdir/projekt
|
167
|
+
prio - - input to prio are planned tasks (see plan)
|
168
|
+
scan x x creates scanned tasks in taskdir/project
|
169
|
+
schedule - - schedules the planned tasks (see plan)
|
170
|
+
start - - starts task from planned tasks (see plan)
|
171
|
+
stop - - stops task from planned task
|
172
|
+
update x x updates task in taskdir/project
|
173
|
+
|
174
|
+
===Files
|
175
|
+
|
176
|
+
* Task files
|
177
|
+
The tasks are named ID.task where ID is any Integer as 10.task. The files are
|
178
|
+
saved as YAML files and can be edited directly.
|
179
|
+
|
180
|
+
* Planned tasks files
|
181
|
+
The planned tasks are save to YYYY-MM-DD_planned_tasks in the default task
|
182
|
+
directory. Each task is saved with the tasks directory and the ID.
|
183
|
+
|
184
|
+
* Schedule files
|
185
|
+
The schedule is saved to YYYY-MM-DD_schedule in the default task directory. The
|
186
|
+
files are saved as YAML files and can be changed manually.
|
187
|
+
|
188
|
+
==Working with syctask
|
189
|
+
To work with syctask and get the most out of it there is to follow a certain
|
190
|
+
process.
|
191
|
+
|
192
|
+
===Creating a schedule
|
193
|
+
==== View tasks
|
194
|
+
In the morning before I start to work I scan my tasks with syctask list to get
|
195
|
+
an overview of my open tasks.
|
196
|
+
$ syctask list
|
197
|
+
|
198
|
+
==== Plan tasks
|
199
|
+
Next I start the planning phase with syctask plan. If I have a specific schedule
|
200
|
+
for the day I will filter for the respective tasks
|
201
|
+
$ syctask plan
|
202
|
+
|
203
|
+
==== Prioritize tasks (optionally)
|
204
|
+
If I want to process the tasks in a specific sequence I prioritize the tasks
|
205
|
+
with
|
206
|
+
$ syctask prio
|
207
|
+
|
208
|
+
==== Create schedule
|
209
|
+
I create a schedule with my working hours and meetings that have been scheduled with
|
210
|
+
$ syctask -w "8:00-18:00" -b "9:00-10:00,14:30-16:00" -m "Team,Status"
|
211
|
+
|
212
|
+
==== Create an agenda
|
213
|
+
I assign the topics I want to discuss in the meetings to the meetings with
|
214
|
+
syctask schedule -a "A:1,3,6;B:3,5"
|
215
|
+
|
216
|
+
==== Start a task
|
217
|
+
To begin I start the first task in the schedule with syctask start 0 (where 0 is the sequence of the planned tasks, the ID is different e.g. 23)
|
218
|
+
$ syctask start 0
|
219
|
+
|
220
|
+
==== End a task
|
221
|
+
To end the task I invoke
|
222
|
+
$ syctask stop
|
223
|
+
This will stop the last started task
|
224
|
+
|
225
|
+
==== Complete a task
|
226
|
+
When the task is done I call
|
227
|
+
$ syctask done 23
|
228
|
+
|
229
|
+
===Attachements
|
230
|
+
* E-mails
|
231
|
+
If an e-mail creates a task I create a new task with syctask new title_of_task.
|
232
|
+
The subject of the e-mail I prepend with the ID and move the e-mail to a
|
233
|
+
<b>open topics</b> directory.
|
234
|
+
|
235
|
+
* Files
|
236
|
+
If I create files in the course of a task I create a folder in the task
|
237
|
+
directory with the ID and save the files in this directory. If there is an
|
238
|
+
existing directory I link to the file from the ID directory
|
239
|
+
|
112
240
|
==Supported platform
|
113
241
|
syc-task has been tested with 1.9.3
|
114
242
|
|
243
|
+
==Add TAB-completion to syctask
|
244
|
+
To activate bash's TAB-completion following lines have to be added to ~/.bashrc
|
245
|
+
|
246
|
+
complete -F get_syctask_commands syctask
|
247
|
+
|
248
|
+
function get_syctask_commands
|
249
|
+
{
|
250
|
+
if [ -z $2 ] ; then
|
251
|
+
COMPREPLY=(`syctask help -c`)
|
252
|
+
else
|
253
|
+
COMPREPLY=(`syctask help -c $2`)
|
254
|
+
fi
|
255
|
+
}
|
256
|
+
|
257
|
+
After ~/.bashrc has been updated the shell session has to be restarted with
|
258
|
+
$ source ~/.bashrc
|
259
|
+
|
260
|
+
Now syctask followed by TAB TAB will print
|
261
|
+
|
262
|
+
$ syctask <TAB><TAB>
|
263
|
+
delete done list plan scan stop _doc help new prio schedule start update
|
264
|
+
|
265
|
+
To complete a command we can type
|
266
|
+
|
267
|
+
$ syctask sch<TAB>
|
268
|
+
|
269
|
+
which will complete to
|
270
|
+
|
271
|
+
$ syctask schedule
|
272
|
+
|
273
|
+
==Output to Printer
|
274
|
+
To print syctask's output to a printer pipe the command to lpr
|
275
|
+
|
276
|
+
$ syctask schedule | lpr
|
277
|
+
|
278
|
+
This will print the schedule to the default printer.
|
279
|
+
|
280
|
+
To determine all available printer lpstat can be used with the lpstat -a command
|
281
|
+
|
282
|
+
$ lpstat -a
|
283
|
+
Canon-LBP6650-3470 accepting requests since Sat 16 Mar 2013 04:26:15 PM CET
|
284
|
+
Dell-B1160w-Mono accepting requests since Sat 16 Mar 2013 04:27:45 PM CET
|
285
|
+
|
286
|
+
To print to Dell-B1160w-Mono the following command can be used
|
287
|
+
|
288
|
+
$ syctask schedule | lpr -P Dell-B1160w-Mono
|
289
|
+
|
115
290
|
==Notes
|
116
|
-
|
291
|
+
With version 0.0.1 new, update, list and done is implemented.
|
292
|
+
with version 0.0.4 start, stop, scan and prio is not implemented.
|
117
293
|
|
118
294
|
The test files live in the folder test and start with test_.
|
119
295
|
|
120
296
|
There is a rake file available to run all tests
|
121
|
-
$ rake test
|
122
297
|
|
298
|
+
$ rake test
|
299
|
+
|
123
300
|
==License
|
124
301
|
syc-task is released under the {MIT License}[http://opensource.org/licenses/MIT]
|
125
302
|
|
data/bin/syctask
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require 'gli'
|
3
3
|
require 'syctask'
|
4
4
|
include GLI::App
|
5
|
+
include Syctime
|
5
6
|
|
6
7
|
program_desc 'A simple task manager'
|
7
8
|
|
@@ -55,6 +56,7 @@ command :new do |c|
|
|
55
56
|
task_numbers = nil
|
56
57
|
args.each do |title|
|
57
58
|
task_number = @service.create(global_options[:t], options, title)
|
59
|
+
add_task_to_plan @service.read(global_options[:t], task_number)
|
58
60
|
if task_numbers.nil?
|
59
61
|
task_numbers = task_number.to_s
|
60
62
|
else
|
@@ -219,6 +221,10 @@ command :plan do |c|
|
|
219
221
|
c.arg_name 'complete'
|
220
222
|
c.switch [:c, :complete]
|
221
223
|
|
224
|
+
c.desc 'Move planned task to another day'
|
225
|
+
c.arg_name 'DATE'
|
226
|
+
c.flag [:m, :move], :must_match => /today|tomorrow|\d{4}-\d{2}-\d{2}/
|
227
|
+
|
222
228
|
c.desc 'Filter for ID'
|
223
229
|
c.arg_name 'ID1,ID2,ID3|[<|=|>]ID'
|
224
230
|
c.flag [:i, :id], :must_match => /^\d+(?:,\d+)*|^[<|=|>]\d+/
|
@@ -253,8 +259,11 @@ command :plan do |c|
|
|
253
259
|
|
254
260
|
c.action do |global_options,options,args|
|
255
261
|
ARGV.clear
|
262
|
+
|
263
|
+
# Any option that is no filter has to be captured before filter is created
|
256
264
|
show = options[:show]
|
257
265
|
complete = options[:complete]
|
266
|
+
to_date = extract_time(options[:move]) if options[:move]
|
258
267
|
|
259
268
|
filter = [:id, :tags, :description, :prio, :due_date, :follow_up,
|
260
269
|
:note, :title]
|
@@ -282,6 +291,9 @@ command :plan do |c|
|
|
282
291
|
end
|
283
292
|
STDOUT.puts sprintf("--> found %d planned task(s) for %s", count, date).
|
284
293
|
color(:green)
|
294
|
+
elsif to_date
|
295
|
+
count = @planner.move_tasks(options, date, to_date)
|
296
|
+
STDOUT.puts sprintf("--> %d task(s) moved", count).color(:green)
|
285
297
|
else
|
286
298
|
count = @planner.plan_tasks(@service.find(global_options[:t], options,
|
287
299
|
false), date)
|
@@ -355,25 +367,81 @@ command :schedule do |c|
|
|
355
367
|
end
|
356
368
|
end
|
357
369
|
|
358
|
-
desc 'Prioritize tasks'
|
370
|
+
desc 'Prioritize tasks of today, tomorrow or another day'
|
371
|
+
arg_name 'DATE'
|
372
|
+
default_value 'today'
|
359
373
|
command :prio do |c|
|
374
|
+
|
375
|
+
c.desc 'Prioritize in specified order'
|
376
|
+
c.arg_name 'ID1,ID2,ID3,...'
|
377
|
+
c.flag [:o, :order], :must_match => /^\d+(?:,\d+)*/
|
378
|
+
|
360
379
|
c.action do |global_options,options,args|
|
361
|
-
|
380
|
+
time = extract_time(args[0])
|
381
|
+
planner = Syctask::TaskPlanner.new
|
382
|
+
if options[:order]
|
383
|
+
ordered, rest = planner.order_tasks(time, options[:order].split(","))
|
384
|
+
puts sprintf("--> put %d task%s into new order and %d appended to end",
|
385
|
+
ordered, "#{'s' if ordered > 1}", rest).color(:green)
|
386
|
+
else
|
387
|
+
planner.prioritize_tasks(time)
|
388
|
+
end
|
362
389
|
end
|
363
390
|
end
|
364
391
|
|
365
|
-
desc 'Start
|
366
|
-
arg_name 'TASK_NUMBER'
|
392
|
+
desc 'Start tracking a task'
|
393
|
+
arg_name 'TASK_NUMBER|PLAN|TALK|PHONE|EMAIL'
|
367
394
|
command :start do |c|
|
395
|
+
|
396
|
+
c.desc 'List currently tracked task'
|
397
|
+
c.switch [:l, :list]
|
398
|
+
|
399
|
+
c.desc 'Number of planned task'
|
400
|
+
c.switch [:p, :plan]
|
401
|
+
|
368
402
|
c.action do |global_options,options,args|
|
369
|
-
|
403
|
+
tracker = Syctask::TaskTracker.new
|
404
|
+
if args[0]
|
405
|
+
if options[:plan]
|
406
|
+
task = @planner.get_tasks[args[0].to_i]
|
407
|
+
else
|
408
|
+
task = @service.read(global_options[:taskdir], args[0])
|
409
|
+
end
|
410
|
+
help_now! sprintf("%s",
|
411
|
+
"no task with id #{args[0]}").color(:red) unless task
|
412
|
+
started, stopped = tracker.start(task)
|
413
|
+
if started
|
414
|
+
puts sprintf("--> tracking %s",
|
415
|
+
"#{task.id} - #{task.title}").color(:green)
|
416
|
+
else
|
417
|
+
puts sprintf("--> allready tracking %s",
|
418
|
+
"#{task.id} - #{task.title}").color(:red)
|
419
|
+
end
|
420
|
+
if stopped
|
421
|
+
puts sprintf("--> stopped %s",
|
422
|
+
"#{stopped.id} - #{stopped.title}").color(:green)
|
423
|
+
puts sprintf(" %s", "#{string_for_seconds(stopped.lead_time)}").color(:green)
|
424
|
+
end
|
425
|
+
end
|
426
|
+
if options[:list]
|
427
|
+
task = tracker.tracked_task
|
428
|
+
puts sprintf("%s", "--> no task tracked").color(:red) unless task
|
429
|
+
puts sprintf("%s", "--> #{task.id} - #{task.title}").color(:green) if task
|
430
|
+
end
|
370
431
|
end
|
371
432
|
end
|
372
433
|
|
373
|
-
desc 'Stop the
|
434
|
+
desc 'Stop the tracked task'
|
374
435
|
command :stop do |c|
|
375
436
|
c.action do |global_options,options,args|
|
376
|
-
|
437
|
+
tracker = Syctask::TaskTracker.new
|
438
|
+
task = tracker.stop
|
439
|
+
if task
|
440
|
+
puts sprintf("--> stopped %s", "#{task.id} - #{task.title}").color(:green)
|
441
|
+
puts sprintf(" %4s", "#{string_for_seconds(task.lead_time)}").color(:green)
|
442
|
+
else
|
443
|
+
puts sprintf("--> %s", "no task tracked").color(:red)
|
444
|
+
end
|
377
445
|
end
|
378
446
|
end
|
379
447
|
|
@@ -411,9 +479,12 @@ command :update do |c|
|
|
411
479
|
options.keep_if {|key, value| filter.find_index(key) and value != nil}
|
412
480
|
|
413
481
|
success = @service.update(global_options[:t], args[0], options)
|
414
|
-
|
482
|
+
|
483
|
+
add_task_to_plan @service.read(global_options[:t], args[0]) if success
|
484
|
+
|
485
|
+
STDOUT.puts sprintf("--> sucessfully updated task with TASK_NUMBER %s ",
|
415
486
|
args[0]).color(:green) if success
|
416
|
-
STDOUT.puts sprintf("could not update task with TASK_NUMBER ",
|
487
|
+
STDOUT.puts sprintf("--> could not update task with TASK_NUMBER %s ",
|
417
488
|
args[0]).color(:red) unless success
|
418
489
|
end
|
419
490
|
end
|
@@ -431,7 +502,8 @@ command :done do |c|
|
|
431
502
|
c.flag [:n, :note]
|
432
503
|
|
433
504
|
c.action do |global_options,options,args|
|
434
|
-
help_now!(
|
505
|
+
help_now! sprintf("%s",
|
506
|
+
'TASK_NUMBER is required').color(:red) if args.empty?
|
435
507
|
task = @service.read(global_options[:t], args[0])
|
436
508
|
exit_now!("Task with TASK_NUMBER #{args[0]} does not exist") unless task
|
437
509
|
task.done(options[:note])
|
@@ -471,4 +543,34 @@ on_error do |exception|
|
|
471
543
|
true
|
472
544
|
end
|
473
545
|
|
546
|
+
# Extracts the time out of a time string. Accepts 'today', 'tomorrow' or a date
|
547
|
+
# in the form 'YYYY-MM-DD'. Returns the date contained in the time_string
|
548
|
+
def extract_time(time_string)
|
549
|
+
time_string = 'today' if time_string.nil?
|
550
|
+
case time_string.downcase
|
551
|
+
when 'today'
|
552
|
+
date = Time.now.strftime("%Y-%m-%d")
|
553
|
+
when 'tomorrow'
|
554
|
+
date = (Time.now + (60 * 60 * 24)).strftime("%Y-%m-%d")
|
555
|
+
else
|
556
|
+
if time_string.match(/\d{4}-\d{2}-\d{2}/)
|
557
|
+
date = time_string
|
558
|
+
elsif nil
|
559
|
+
date = Time.now.strftime("%Y-%m-%d")
|
560
|
+
else
|
561
|
+
help_now! "Arguments may be 'today', 'tomorrow', YYYY-MM-DD or <RETURN>"
|
562
|
+
end
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
# Add task to task plan
|
567
|
+
def add_task_to_plan(task)
|
568
|
+
if task.options[:follow_up]
|
569
|
+
@planner.add_task(task, task.options[:follow_up])
|
570
|
+
end
|
571
|
+
if task.options[:due_date]
|
572
|
+
@planner.add_task(task, task.options[:due_date])
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
474
576
|
exit run(ARGV)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Sycstring
|
2
|
+
|
3
|
+
# Splits a string to size (chars) less or equal to length
|
4
|
+
def split_lines(string, length)
|
5
|
+
lines = string.squeeze(" ").split("\n")
|
6
|
+
i = 0
|
7
|
+
new_lines = []
|
8
|
+
new_lines[i] = ""
|
9
|
+
lines.each do |line|
|
10
|
+
line.squeeze(" ").split.each do |w|
|
11
|
+
if new_lines[i].length + w.length < length
|
12
|
+
new_lines[i] += "#{w} "
|
13
|
+
else
|
14
|
+
i += 1
|
15
|
+
new_lines[i] = "#{w} "
|
16
|
+
end
|
17
|
+
end
|
18
|
+
i += 1
|
19
|
+
new_lines[i] = ""
|
20
|
+
end
|
21
|
+
text = ""
|
22
|
+
new_lines.each {|l| text << "#{l}\n"}
|
23
|
+
text.chomp
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
data/lib/syctask.rb
CHANGED
@@ -6,6 +6,8 @@ require 'syctask/task_scheduler.rb'
|
|
6
6
|
require 'syctask/task_planner.rb'
|
7
7
|
require 'syctask/schedule.rb'
|
8
8
|
require 'sycutil/console.rb'
|
9
|
+
require 'syctask/task_tracker.rb'
|
10
|
+
require 'syctime/time_util.rb'
|
9
11
|
|
10
12
|
# Add requires for other files you add to your project here, so
|
11
13
|
# you just need to require this one file in your bin file
|
data/lib/syctask/meeting.rb
CHANGED
@@ -2,11 +2,17 @@ require_relative 'times.rb'
|
|
2
2
|
|
3
3
|
module Syctask
|
4
4
|
|
5
|
-
|
5
|
+
# Meeting represents a meeting containing the begin and end time, a title and
|
6
|
+
# an agenda consisting of tasks
|
7
|
+
class Meeting
|
6
8
|
|
9
|
+
# The start time of the meeting
|
7
10
|
attr_accessor :starts
|
11
|
+
# The end time of the meeting
|
8
12
|
attr_accessor :ends
|
13
|
+
# The title of the meeting
|
9
14
|
attr_accessor :title
|
15
|
+
# The agenda or tasks of the meeting
|
10
16
|
attr_accessor :tasks
|
11
17
|
|
12
18
|
# Sets the busy time for the schedule. The busy times have to be provided
|
data/lib/syctask/schedule.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require_relative 'times.rb'
|
2
2
|
require_relative 'meeting.rb'
|
3
|
+
require_relative '../sycstring/string_util.rb'
|
4
|
+
include Sycstring
|
3
5
|
|
4
6
|
module Syctask
|
5
7
|
|
@@ -243,8 +245,11 @@ module Syctask
|
|
243
245
|
else
|
244
246
|
color = WORK_COLOR
|
245
247
|
end
|
246
|
-
|
247
|
-
|
248
|
+
offset = max_ord_size + max_id_size + 5
|
249
|
+
title = split_lines(task.title, 80-offset)
|
250
|
+
title = title.chomp.gsub(/\n/, "\n#{' '*offset}")
|
251
|
+
task_list << sprintf("%#{max_ord_size}d: %#{max_id_size}s - %s\n",
|
252
|
+
i, task.id, title).color(color)
|
248
253
|
end
|
249
254
|
|
250
255
|
task_caption = ""
|
data/lib/syctask/task.rb
CHANGED
@@ -26,6 +26,8 @@ module Syctask
|
|
26
26
|
attr_reader :id
|
27
27
|
# Duration specifies the planned time for processing the task
|
28
28
|
attr_accessor :duration
|
29
|
+
# Lead time is the time this task has been processed
|
30
|
+
attr_accessor :lead_time
|
29
31
|
# Creation date
|
30
32
|
attr_reader :creation_date
|
31
33
|
# Update date
|
@@ -74,10 +76,12 @@ module Syctask
|
|
74
76
|
when :note
|
75
77
|
new_value = "#{@update_date}\n#{new_value}\n#{@options[key]}"
|
76
78
|
when :tags
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
79
|
+
unless @options[key].nil?
|
80
|
+
if @options[key].include? new_value
|
81
|
+
new_value = @options[key]
|
82
|
+
else
|
83
|
+
new_value = "#{@options[key]},#{new_value}"
|
84
|
+
end
|
81
85
|
end
|
82
86
|
end
|
83
87
|
|
@@ -184,16 +188,22 @@ module Syctask
|
|
184
188
|
def pretty_string(long)
|
185
189
|
color = :default
|
186
190
|
color = :green if self.done?
|
191
|
+
|
192
|
+
title = split_lines(@title, 70)
|
193
|
+
title = title.chomp.gsub(/\n/, "\n#{' '*7}")
|
194
|
+
puts sprintf("%04d - %s", @id, title.bright).color(color)
|
187
195
|
|
188
|
-
puts sprintf("%04d - %s", @id, @title.bright).color(color)
|
189
196
|
if @options[:description]
|
190
197
|
description = split_lines(@options[:description].chomp, 70)
|
191
198
|
description = description.chomp.gsub(/\n/, "\n#{' '*7}")
|
192
199
|
puts sprintf("%6s %s", " ", description.chomp).color(color)
|
193
200
|
end
|
194
|
-
puts sprintf("%6s Prio: %s", " ", @options[:prio]).
|
195
|
-
|
196
|
-
puts sprintf("%6s
|
201
|
+
puts sprintf("%6s Prio: %s", " ", @options[:prio]).
|
202
|
+
color(color) if @options[:prio]
|
203
|
+
puts sprintf("%6s Follow-up: %s", " ", @options[:follow_up]).
|
204
|
+
color(color) if @options[:follow_up]
|
205
|
+
puts sprintf("%6s Due: %s", " ", @options[:due_date]).
|
206
|
+
color(color) if @options[:due_date]
|
197
207
|
if long
|
198
208
|
if @options[:note]
|
199
209
|
note = split_lines(@options[:note].chomp, 70)
|
@@ -203,10 +213,13 @@ module Syctask
|
|
203
213
|
gsub(/\n(?=\d{4}-\d{2}-\d{2} - \d{2}:\d{2}:\d{2})/, "\n#{' '*7}")
|
204
214
|
puts sprintf("%6s %s", " ", note.chomp).color(color)
|
205
215
|
end
|
206
|
-
puts sprintf("%6s Tags: %s", " ", @options[:tags]).
|
216
|
+
puts sprintf("%6s Tags: %s", " ", @options[:tags]).
|
217
|
+
color(color) if @options[:tags]
|
207
218
|
puts sprintf("%6s Created: %s", " ", @creation_date).color(color)
|
208
|
-
puts sprintf("%6s Updated: %s", " ", @update_date).
|
209
|
-
|
219
|
+
puts sprintf("%6s Updated: %s", " ", @update_date).
|
220
|
+
color(color) if @update_date
|
221
|
+
puts sprintf("%6s Closed: %s", " ", @done_date).
|
222
|
+
color(color) if @done_date
|
210
223
|
end
|
211
224
|
end
|
212
225
|
|
@@ -217,7 +230,7 @@ module Syctask
|
|
217
230
|
def csv_string
|
218
231
|
string = "\n#{@id};#{@title};"
|
219
232
|
string +" #{@options[:description]};#{@options[:prio]};"
|
220
|
-
string += "#{@options[:follow_up]};#{@options[:
|
233
|
+
string += "#{@options[:follow_up]};#{@options[:due_date]};"
|
221
234
|
string += "#{@options[:note].gsub(/\n/, '\\n')};"
|
222
235
|
string += "#{@options[:tags]};"
|
223
236
|
string += "#{@creation_date};"
|
data/lib/syctask/task_planner.rb
CHANGED
@@ -3,11 +3,18 @@ require_relative '../sycutil/console.rb'
|
|
3
3
|
require_relative 'task_service.rb'
|
4
4
|
|
5
5
|
module Syctask
|
6
|
+
# String that is prompted during planning
|
6
7
|
PROMPT_STRING = '(a)dd, (c)omplete, (s)kip, (q)uit: '
|
8
|
+
# String that is prompted during prioritization
|
9
|
+
PRIORITIZE_STRING = 'Task 1 has (h)igher or (l)ower priority, or (q)uit: '
|
7
10
|
|
11
|
+
# A TaskPlanner prompts the user to select tasks for today. These tasks can
|
12
|
+
# be prioritized to determine the most to the least important tasks.
|
8
13
|
class TaskPlanner
|
14
|
+
# The task where the planned tasks are saved to
|
9
15
|
WORK_DIR = File.expand_path("~/.tasks")
|
10
16
|
|
17
|
+
# Creates a new TaskPlanner
|
11
18
|
def initialize
|
12
19
|
@console = Sycutil::Console.new
|
13
20
|
@service = TaskService.new
|
@@ -54,9 +61,75 @@ module Syctask
|
|
54
61
|
count
|
55
62
|
end
|
56
63
|
|
57
|
-
#
|
58
|
-
|
59
|
-
|
64
|
+
# Order tasks in the provided IDs sequence at the specified date. If not
|
65
|
+
# IDs are provided than rest of tasks is appended to the end of the plan.
|
66
|
+
# Returns the count of ordered tasks and the count of the rest of the tasks.
|
67
|
+
def order_tasks(date, ids)
|
68
|
+
tasks = get_tasks(date)
|
69
|
+
ordered = []
|
70
|
+
ids.each do |id|
|
71
|
+
index = tasks.find_index {|t| t.id == id.to_i}
|
72
|
+
ordered << tasks.delete_at(index) if index
|
73
|
+
end
|
74
|
+
ordered << tasks
|
75
|
+
save_tasks(ordered.flatten!, true)
|
76
|
+
[ordered.size - tasks.size, tasks.size]
|
77
|
+
end
|
78
|
+
|
79
|
+
# Prioritize tasks by pair wise comparisson. Each task is compared to the
|
80
|
+
# other tasks and the user can select the task with the higher priority. So
|
81
|
+
# the task with highest priority will bubble on top followed by the task
|
82
|
+
# with second highest priority and so on.
|
83
|
+
def prioritize_tasks(date=Time.now.strftime("%Y-%m-%d"), filter={})
|
84
|
+
tasks = get_tasks(date, filter)
|
85
|
+
return false if tasks.nil?
|
86
|
+
quit = false
|
87
|
+
0.upto(tasks.size-1) do |i|
|
88
|
+
(i+1).upto(tasks.size-1) do |j|
|
89
|
+
puts " 1: #{tasks[i].title}"
|
90
|
+
puts " 2: #{tasks[j].title}"
|
91
|
+
choice = @console.prompt PRIORITIZE_STRING
|
92
|
+
case choice
|
93
|
+
when 'q'
|
94
|
+
quit = true
|
95
|
+
break
|
96
|
+
when 'l'
|
97
|
+
tasks[i],tasks[j] = tasks[j],tasks[i]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
break if quit
|
101
|
+
end
|
102
|
+
save_tasks(tasks, true)
|
103
|
+
true
|
104
|
+
end
|
105
|
+
|
106
|
+
# Add the task to the planned tasks of the specified date. The task is only
|
107
|
+
# added if not already present
|
108
|
+
def add_task(task, date=Time.now.strftime("%Y-%m-%d"))
|
109
|
+
add_tasks([task], date)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Add the tasks to the planned tasks. A task is only added if not already
|
113
|
+
# present
|
114
|
+
def add_tasks(tasks, date=Time.now.strftime("%Y-%m-%d"))
|
115
|
+
planned = get_tasks(date)
|
116
|
+
tasks.each do |task|
|
117
|
+
planned << task unless planned.find_index {|t| t == task}
|
118
|
+
end
|
119
|
+
save_tasks(planned, true)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Moves the specified tasks to the specified date. Returns the count of
|
123
|
+
# moved files
|
124
|
+
def move_tasks(filter={}, from_date=Time.now.strftime("%Y-%m-%d"), to_date)
|
125
|
+
return 0 if from_date == to_date
|
126
|
+
moved = get_tasks(from_date, filter)
|
127
|
+
moved.each do |task|
|
128
|
+
task.options[:follow_up] = to_date
|
129
|
+
@service.save(task.dir, task)
|
130
|
+
end
|
131
|
+
add_tasks(moved, to_date)
|
132
|
+
remove_tasks(from_date, filter)
|
60
133
|
end
|
61
134
|
|
62
135
|
# Remove planned tasks from the task plan based on the provided filter
|
@@ -67,6 +140,15 @@ module Syctask
|
|
67
140
|
tasks.each do |task|
|
68
141
|
planned << task unless task.matches?(filter)
|
69
142
|
end
|
143
|
+
(tasks - planned).each do |task|
|
144
|
+
if task.options[:follow_up] == date
|
145
|
+
task.options[:follow_up] = nil
|
146
|
+
end
|
147
|
+
if task.options[:due_date] == date
|
148
|
+
task.options[:due_date] = nil
|
149
|
+
end
|
150
|
+
@service.save(task.dir, task)
|
151
|
+
end
|
70
152
|
save_tasks(planned, true)
|
71
153
|
tasks.size - planned.size
|
72
154
|
end
|
data/lib/syctask/task_service.rb
CHANGED
@@ -6,6 +6,8 @@ module Syctask
|
|
6
6
|
# Provides services to operate tasks as create, read, find, update and save
|
7
7
|
# Task objects
|
8
8
|
class TaskService
|
9
|
+
# Default directory where the tasks are saved to if no directory is
|
10
|
+
# specified
|
9
11
|
DEFAULT_DIR = File.expand_path("~/.tasks")
|
10
12
|
|
11
13
|
# Creates a new task in the specified directory, with the specified options
|
@@ -29,7 +31,7 @@ module Syctask
|
|
29
31
|
# does not exist nil is returned otherwise the task is returned
|
30
32
|
def read(dir, id)
|
31
33
|
task = nil
|
32
|
-
Dir.glob("#{dir}
|
34
|
+
Dir.glob("#{dir}/*.task").each do |file|
|
33
35
|
task = YAML.load_file(file) if File.file? file
|
34
36
|
if not task.nil? and task.class == Syctask::Task and task.id == id.to_i
|
35
37
|
return task
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require_relative 'environment.rb'
|
2
|
+
require_relative 'task_service.rb'
|
3
|
+
|
4
|
+
module Syctask
|
5
|
+
|
6
|
+
# TaskTracker provides methods to start a task and stop a task. The objective
|
7
|
+
# is to track the processing time for a task. The processing time can be
|
8
|
+
# analyzed with the TaskStatistics class. When a task is started it is saved
|
9
|
+
# to the started_tasks file. If another task is started the currently active
|
10
|
+
# task is stopped and the newly started file is put on top of the
|
11
|
+
# started_tasks file. When stopping a task the currently started tasks will
|
12
|
+
# be returned and one of the idling tasks can be restarted. When a task is
|
13
|
+
# stopped the processing time is added to the task's lead_time field.
|
14
|
+
class TaskTracker
|
15
|
+
|
16
|
+
# File name of the file where the tracked files are saved to
|
17
|
+
TRACKED_TASKS_FILE = Syctask::WORK_DIR + '/' + 'tracked_tasks'
|
18
|
+
# File name of the task log file
|
19
|
+
TASK_LOG_FILE = Syctask::WORK_DIR + '/' + 'tasks.log'
|
20
|
+
|
21
|
+
# Creates a new TaskTracker
|
22
|
+
def initialize
|
23
|
+
@service = Syctask::TaskService.new
|
24
|
+
load_tracks
|
25
|
+
end
|
26
|
+
|
27
|
+
# When a task is started it is saved with the start time. If a task is
|
28
|
+
# already tracked it is stopped (see #stop). A started task will print
|
29
|
+
# every 15 minutes a message to the console.
|
30
|
+
# start returns
|
31
|
+
# * [false, nil ] if the task is already tracked
|
32
|
+
# * [true, nil ] if the task is started and no task was running.
|
33
|
+
# * [true, task] if task is started and the previously running task stopped
|
34
|
+
def start(task)
|
35
|
+
index = @tasks.find_index(task)
|
36
|
+
return [false, nil] if not index.nil? and index == 0
|
37
|
+
|
38
|
+
stopped_task = stop
|
39
|
+
track = Track.new(task)
|
40
|
+
|
41
|
+
track.start
|
42
|
+
log_task(:start, track)
|
43
|
+
|
44
|
+
@tracks.insert(0,track)
|
45
|
+
|
46
|
+
@tasks.insert(0,task)
|
47
|
+
|
48
|
+
save_tracks
|
49
|
+
|
50
|
+
[true, stopped_task]
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
# When a task is stopped it is removed from the started_tasks file and the
|
55
|
+
# processing time is added to the lead_time field of the task. #stop
|
56
|
+
# returns the stopped task in an Array or an empty Array if no task is
|
57
|
+
# running an hence no task can be stopped.
|
58
|
+
def stop
|
59
|
+
return nil unless @tasks[0]
|
60
|
+
|
61
|
+
task = @tasks[0]
|
62
|
+
if task.lead_time
|
63
|
+
task.lead_time += @tracks[0].stop
|
64
|
+
else
|
65
|
+
task.lead_time = @tracks[0].stop
|
66
|
+
end
|
67
|
+
|
68
|
+
@service.save(task.dir, task)
|
69
|
+
log_task(:stop, @tracks[0])
|
70
|
+
|
71
|
+
@tracks.delete_at(0)
|
72
|
+
@tasks.delete_at(0)
|
73
|
+
save_tracks
|
74
|
+
task
|
75
|
+
end
|
76
|
+
|
77
|
+
# Retrieves the currently tracked task returns nil if no task is tracked
|
78
|
+
def tracked_task
|
79
|
+
@tasks[0]
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
# Saves the tracks to the tracked tasks file
|
85
|
+
def save_tracks
|
86
|
+
FileUtils.mkdir_p WORK_DIR unless File.exists? WORK_DIR
|
87
|
+
File.open(TRACKED_TASKS_FILE, 'w') do |file|
|
88
|
+
YAML.dump(@tracks, file)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Loads the tracks from the tracked tasks file to @tasks and
|
93
|
+
# @tracks. If no tracked tasks exist @tracks and @tasks will be
|
94
|
+
# empty
|
95
|
+
def load_tracks
|
96
|
+
unless File.exists? TRACKED_TASKS_FILE
|
97
|
+
@tracks = []
|
98
|
+
@tasks = []
|
99
|
+
else
|
100
|
+
@tracks ||= YAML.load_file(TRACKED_TASKS_FILE)
|
101
|
+
@tasks = []
|
102
|
+
@tracks.each { |track| @tasks << @service.read(track.dir, track.id) }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Logs the start and stop of a task.
|
107
|
+
def log_task(type, track)
|
108
|
+
FileUtils.mkdir_r Syctask::WORK_DIR unless File.exists? Syctask::WORK_DIR
|
109
|
+
File.open(TASK_LOG_FILE, 'a') do |file|
|
110
|
+
log_entry = "#{type.to_s};"
|
111
|
+
log_entry += "#{track.id}-#{track.dir};"
|
112
|
+
log_entry += "#{track.title};"
|
113
|
+
log_entry += "#{track.started};"
|
114
|
+
log_entry += "#{track.stopped}"
|
115
|
+
file.puts log_entry
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
# A Track holds a task and stops the time the task is processed. The Track
|
122
|
+
# will print every 5 minutes the elapsed time and the time left to the
|
123
|
+
# specified Task#duration.
|
124
|
+
class Track
|
125
|
+
|
126
|
+
# Directory where the tracked task is saved
|
127
|
+
attr_reader :dir
|
128
|
+
# ID of the tracked task
|
129
|
+
attr_reader :id
|
130
|
+
# Title of the tracked task
|
131
|
+
attr_reader :title
|
132
|
+
# When tracking started
|
133
|
+
attr_reader :started
|
134
|
+
# When tracking stopped
|
135
|
+
attr_reader :stopped
|
136
|
+
|
137
|
+
# Creates a new Track for the provided task
|
138
|
+
def initialize(task)
|
139
|
+
@dir = task.dir
|
140
|
+
@id = task.id
|
141
|
+
@title = task.title
|
142
|
+
end
|
143
|
+
|
144
|
+
# Starts the tracking and a timer that will print to STDOUT every 5 minutes
|
145
|
+
# the elapsed time and the time left until Task#duration
|
146
|
+
def start
|
147
|
+
@started ||= Time.now
|
148
|
+
# start a timer that prints title and elapsed time every 5 minutes
|
149
|
+
end
|
150
|
+
|
151
|
+
# Stops the task tracking and returns the lead time of the task
|
152
|
+
def stop
|
153
|
+
@stopped ||= Time.now
|
154
|
+
@stopped - @started
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
data/lib/syctask/times.rb
CHANGED
@@ -1,15 +1,21 @@
|
|
1
1
|
module Syctask
|
2
2
|
|
3
|
+
# Times class represents a time consisting of hour and minutes
|
3
4
|
class Times
|
4
5
|
|
6
|
+
# Hour of the Times object
|
5
7
|
attr_reader :h
|
8
|
+
# Minute of the Times object
|
6
9
|
attr_reader :m
|
7
10
|
|
11
|
+
# Creates a new Times object. time has to be provided as an array with the
|
12
|
+
# content as ["hour","minute"] e.g. ["10","15"] is 15 past 10
|
8
13
|
def initialize(time)
|
9
14
|
@h = time[0].to_i
|
10
15
|
@m = time[1].to_i
|
11
16
|
end
|
12
17
|
|
18
|
+
# Rounds the time to the next hour if minutes is greater than 0
|
13
19
|
def round_up
|
14
20
|
@m > 0 ? @h+1 : @h
|
15
21
|
end
|
data/lib/syctask/version.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Syctime
|
2
|
+
|
3
|
+
def seconds_to_time(seconds)
|
4
|
+
seconds = seconds.round
|
5
|
+
duration = []
|
6
|
+
duration << seconds % 60 # seconds
|
7
|
+
duration << seconds / 60 % 60 # minutes
|
8
|
+
duration << seconds / 60 / 60 % 60 # hours
|
9
|
+
duration << seconds / 60 / 60 / 60 % 24 # days
|
10
|
+
duration << seconds / 60 / 60 / 60 / 24 % 7 # weeks
|
11
|
+
duration << seconds / 60 / 60 / 60 / 24 / 7 % 4 # months
|
12
|
+
duration << seconds / 60 / 60 / 60 / 24 / 7 / 4 % 12 # years
|
13
|
+
end
|
14
|
+
|
15
|
+
def string_for_seconds(seconds)
|
16
|
+
time = seconds_to_time(seconds)
|
17
|
+
time_name = ['year','month','week','day','hour','minute','second']
|
18
|
+
time_string = ""
|
19
|
+
time.reverse.each_with_index do |part,index|
|
20
|
+
time_string << part.to_s + ' ' + time_name[index] + ' ' if part == 1
|
21
|
+
time_string << part.to_s + ' ' + time_name[index] + 's ' if part > 1
|
22
|
+
end
|
23
|
+
time_string
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
data/lib/sycutil/console.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: syc-task
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -91,39 +91,49 @@ dependencies:
|
|
91
91
|
- - ! '>='
|
92
92
|
- !ruby/object:Gem::Version
|
93
93
|
version: '0'
|
94
|
-
description: ! "= Simple task organizer\
|
95
|
-
application can be installed with\n $ gem
|
96
|
-
provides basic task organizer functions as
|
97
|
-
|
98
|
-
not sure in which sequence to conduct the
|
99
|
-
|
100
|
-
tasks from a minutes of meetings file.
|
101
|
-
timeline of the working day assigning the
|
102
|
-
are marked red. Meetings are listed with
|
103
|
-
meetings.\n\n===Create tasks with new\nCreate
|
104
|
-
~/.tasks\n $ syctask new \"My first
|
105
|
-
|
106
|
-
a task with a follow-up and due date\n
|
107
|
-
\"2013-02-25\" --due \"2013-03-11\"\n\nSet
|
108
|
-
new \"My first task\" --prio 3\n\nPrompt for
|
109
|
-
prompt for task titles.
|
110
|
-
you can also provide short forms for the options.\n\n===Plan tasks\nThe
|
111
|
-
will print tasks and prompts whether to (a)dd or (s)kip the task. If
|
112
|
-
the tasks already added will be add to the today's task\nlist.
|
113
|
-
selected the complete task will be printed and the user\nwill be
|
114
|
-
for adding the task.\n\nInvoke plan without filter\n $ syctask
|
115
|
-
My first task\n (a)dd, (c)omplete, (s)kip, (q)uit? a\n Duration
|
116
|
-
return 30 minutes): 3\n --> 1 task(s) planned\n\nInvoke plan
|
117
|
-
\
|
118
|
-
(s)kip, (q)uit?\n\n===
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
\
|
126
|
-
|
94
|
+
description: ! "= Simple task organizer\nsyctask can be used to create, plan, prioritize
|
95
|
+
and schedule tasks.\n\n==Install\nThe application can be installed with\n $ gem
|
96
|
+
install syc-task\n\n== Usage\nsyctask provides basic task organizer functions as
|
97
|
+
create, update, list and complete a task. Additional functions are to plan tasks
|
98
|
+
you want to accomplish today. If you are not sure in which sequence to conduct the
|
99
|
+
task you can prioritize them with a pair wise comparisson. You can time tasks with
|
100
|
+
start and stop and you can finally extract tasks from a minutes of meetings file.
|
101
|
+
The schedule task will print a graphical timeline of the working day assigning the
|
102
|
+
planned tasks to the timeline. Busy times are marked red. Meetings are listed with
|
103
|
+
associated tasks that are assigned to the meetings.\n\n===Create tasks with new\nCreate
|
104
|
+
a new task in the default task directory ~/.tasks\n $ syctask new \"My first
|
105
|
+
task\"\n\nProvide a description\n $ syctask new \"My first task\" --description
|
106
|
+
\"Explanation of my first task\"\n\nSchedule a task with a follow-up and due date\n
|
107
|
+
\ $ syctask new \"My first task\" --follow-up \"2013-02-25\" --due \"2013-03-11\"\n\nSet
|
108
|
+
a proirity for a task\n $ syctask new \"My first task\" --prio 3\n\nPrompt for
|
109
|
+
task input\n $ syctask new\nwill prompt for task titles. Ctrl-D will end input.\n\nExcept
|
110
|
+
for --description you can also provide short forms for the options.\n\n===Plan tasks\nThe
|
111
|
+
plan command will print tasks and prompts whether to (a)dd or (s)kip the task. If
|
112
|
+
(q)uit is selected the tasks already added will be add to the today's task\nlist.
|
113
|
+
If (c)omplete is selected the complete task will be printed and the user\nwill be
|
114
|
+
prompted again for adding the task.\n\nInvoke plan without filter\n $ syctask
|
115
|
+
plan\n 1 - My first task\n (a)dd, (c)omplete, (s)kip, (q)uit? a\n Duration
|
116
|
+
(1 = 15 minutes, return 30 minutes): 3\n --> 1 task(s) planned\n\nInvoke plan
|
117
|
+
with a filter\n $ syctask plan --id \"1,3,5,8\"\n 1 - My first task\n (a)dd,
|
118
|
+
(c)omplete, (s)kip, (q)uit?\n\n===Prioritize tasks\nPlanned tasks can be prioritized
|
119
|
+
in a pair wise comparisson. So each task is\ncompared to all other tasks. The task
|
120
|
+
with the highest priority will bubble on\ntop followed by the task with the next
|
121
|
+
highest priority and so on.\n\n $ syctask prio\n 1: My first task\n 2:
|
122
|
+
My second task\n Task 1 has (h)igher or (l)ower priority, or (q)uit: h\n 1:
|
123
|
+
My first task\n 2: My third task\n Task 1 has (h)igher or (l)ower priority,
|
124
|
+
or (q)uit: l\n 1: My third task\n 2: My fourth task\n Task 1 has (h)igher
|
125
|
+
or (l)ower priority, or (q)uit: h\n ...\n\nsyctask schedule will then print tasks
|
126
|
+
as follows\n Tasks\n -----\n 0: 10 - My fourth task\n 1: 7 - My third
|
127
|
+
task\n 2: 3 - My first task\n 3: 9 - My second task \n ...\n \n===Create
|
128
|
+
schedule\nThe schedule command will print a graphical schedule with assigning the
|
129
|
+
tasks\nadded with plan.\n\nCreate a schedule with working time from 8a.m. to 6p.m.
|
130
|
+
and meetings between\n9a.m. and 9.30a.m. and 1p.m. and 2.45p.m.\n $ syctask schedule
|
131
|
+
-w \"8:00-18:00\" -b \"9:00-9:30,13:00-14:45\"\n\nAdd titles to the meetings\n $
|
132
|
+
syctask schedule -m \"Project status,Management meeting\"\n\nThe output will be\n
|
133
|
+
\ Meetings\n --------\n A - Project status\n B - Management meeting\n\n
|
134
|
+
\ A B\n xxx-///-|---|---|---///////-|---|---|---|\n 8
|
135
|
+
\ 9 10 11 12 13 14 15 16 17 18\n 1\n\n Tasks\n -----\n 0 -
|
136
|
+
1: My first task\n\nAdding a task to a meeting\n $ syctask schedule -a \"A:1\"\n\nwill
|
127
137
|
print\n Meetings\n --------\n A - Project status\n 1 - My first
|
128
138
|
task\n B - Management meeting\n\n A B\n ----///-|---|---|---///////-|---|---|---|\n
|
129
139
|
\ 8 9 10 11 12 13 14 15 16 17 18\n \n\n Tasks\n -----\n \n===List
|
@@ -135,13 +145,78 @@ description: ! "= Simple task organizer\nWith syctask you can organize your task
|
|
135
145
|
task with ID 1 and provide some informative note\n $ syctask update 1 --note
|
136
146
|
\"Some explanation about the progress on the task\"\n\n===Complete tasks\nComplete
|
137
147
|
the task with ID 1 and provide a final note\n $ syctask done 1 --note \"Finalize
|
138
|
-
my first task\"\n\n
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
148
|
+
my first task\"\n\n===Delete tasks\nDelete tasks with ID 1,3 and 5 from the default
|
149
|
+
task directory\n $ syctask delete --id 1,3,5\n\nDelete tasks with ID 8 and 12
|
150
|
+
from the planned tasks of today. The tasks are\nonly removed from the planned tasks
|
151
|
+
and not physically deleted.\n $ syctask delete --plan today --id 8,12\n\n===Task
|
152
|
+
directory and project directory\nThe global options --taskdir and --project determine
|
153
|
+
where the command finds\nor creates the tasks. The default task directory is ~/.tasks,
|
154
|
+
so if no task\ndirectory is specified all commands obtain tasks from or create tasks
|
155
|
+
in\n~/.tasks. If a project is specified the tasks will be saved to or obtained from
|
156
|
+
the task directories subdirectory specified with the --project flag.\n\n --taskdir
|
157
|
+
\ --project Tasks in\n - - default_task_dir\n x -
|
158
|
+
\ task_dir\n - x default_task_dir/project\n x x
|
159
|
+
\ task_dir/project\n\nIn the table the relation of commands to --taskdir and
|
160
|
+
--project are listed.\n\n Command --taskdir --project Comment\n delete
|
161
|
+
\ x x deletes the tasks in taskdir/project \n done x
|
162
|
+
\ x marks tasks in taskdir/project as done\n help - -
|
163
|
+
\ \n list x x lists tasks in taskdir/project\n
|
164
|
+
\ new x x creates tasks in taskdir/project\n plan x
|
165
|
+
\ x retrieves tasks to plan from taskdir/projekt\n prio -
|
166
|
+
\ - input to prio are planned tasks (see plan)\n scan x
|
167
|
+
\ x creates scanned tasks in taskdir/project\n schedule - -
|
168
|
+
\ schedules the planned tasks (see plan)\n start - - starts
|
169
|
+
task from planned tasks (see plan)\n stop - - stops task
|
170
|
+
from planned task\n update x x updates task in taskdir/project
|
171
|
+
\ \n\n===Files\n\n* Task files\nThe tasks are named ID.task where ID is any Integer
|
172
|
+
as 10.task. The files are\nsaved as YAML files and can be edited directly.\n\n*
|
173
|
+
Planned tasks files\nThe planned tasks are save to YYYY-MM-DD_planned_tasks in the
|
174
|
+
default task\ndirectory. Each task is saved with the tasks directory and the ID.\n\n*
|
175
|
+
Schedule files\nThe schedule is saved to YYYY-MM-DD_schedule in the default task
|
176
|
+
directory. The\nfiles are saved as YAML files and can be changed manually.\n\n==Working
|
177
|
+
with syctask\nTo work with syctask and get the most out of it there is to follow
|
178
|
+
a certain\nprocess.\n\n===Creating a schedule\n==== View tasks\nIn the morning before
|
179
|
+
I start to work I scan my tasks with syctask list to get\nan overview of my open
|
180
|
+
tasks.\n $ syctask list\n \n==== Plan tasks\nNext I start the planning phase
|
181
|
+
with syctask plan. If I have a specific schedule\nfor the day I will filter for
|
182
|
+
the respective tasks\n $ syctask plan\n\n==== Prioritize tasks (optionally)\nIf
|
183
|
+
I want to process the tasks in a specific sequence I prioritize the tasks\nwith
|
184
|
+
\n $ syctask prio\n\n==== Create schedule\nI create a schedule with my working
|
185
|
+
hours and meetings that have been scheduled with \n $ syctask -w \"8:00-18:00\"
|
186
|
+
-b \"9:00-10:00,14:30-16:00\" -m \"Team,Status\"\n\n==== Create an agenda\nI assign
|
187
|
+
the topics I want to discuss in the meetings to the meetings with\n syctask schedule
|
188
|
+
-a \"A:1,3,6;B:3,5\"\n \n==== Start a task\nTo begin I start the first task in
|
189
|
+
the schedule with syctask start 0 (where 0 is the sequence of the planned tasks,
|
190
|
+
the ID is different e.g. 23)\n $ syctask start 0\n\n==== End a task\nTo end the
|
191
|
+
task I invoke \n $ syctask stop\nThis will stop the last started task\n\n====
|
192
|
+
Complete a task\nWhen the task is done I call \n $ syctask done 23\n\n===Attachements\n*
|
193
|
+
E-mails\nIf an e-mail creates a task I create a new task with syctask new title_of_task.\nThe
|
194
|
+
subject of the e-mail I prepend with the ID and move the e-mail to a\n<b>open topics</b>
|
195
|
+
directory.\n\n* Files\nIf I create files in the course of a task I create a folder
|
196
|
+
in the task\ndirectory with the ID and save the files in this directory. If there
|
197
|
+
is an\nexisting directory I link to the file from the ID directory\n\n==Supported
|
198
|
+
platform\nsyc-task has been tested with 1.9.3\n\n==Add TAB-completion to syctask\nTo
|
199
|
+
activate bash's TAB-completion following lines have to be added to ~/.bashrc\n\n
|
200
|
+
\ complete -F get_syctask_commands syctask\n\n function get_syctask_commands\n
|
201
|
+
\ {\n if [ -z $2 ] ; then\n COMPREPLY=(`syctask help -c`)\n else\n
|
202
|
+
\ COMPREPLY=(`syctask help -c $2`)\n fi\n }\n\nAfter ~/.bashrc has
|
203
|
+
been updated the shell session has to be restarted with\n $ source ~/.bashrc\n\nNow
|
204
|
+
syctask followed by TAB TAB will print\n\n $ syctask <TAB><TAB>\n delete done
|
205
|
+
list plan scan stop _doc help new prio schedule start update\n \nTo complete a command
|
206
|
+
we can type\n\n $ syctask sch<TAB>\n\nwhich will complete to\n\n $ syctask
|
207
|
+
schedule\n\n==Output to Printer\nTo print syctask's output to a printer pipe the
|
208
|
+
command to lpr\n\n $ syctask schedule | lpr\n\nThis will print the schedule to
|
209
|
+
the default printer. \n\nTo determine all available printer lpstat can be used with
|
210
|
+
the lpstat -a command\n\n $ lpstat -a\n Canon-LBP6650-3470 accepting requests
|
211
|
+
since Sat 16 Mar 2013 04:26:15 PM CET\n Dell-B1160w-Mono accepting requests since
|
212
|
+
Sat 16 Mar 2013 04:27:45 PM CET\n \nTo print to Dell-B1160w-Mono the following
|
213
|
+
command can be used\n\n $ syctask schedule | lpr -P Dell-B1160w-Mono\n\n==Notes\nWith
|
214
|
+
version 0.0.1 new, update, list and done is implemented.\nwith version 0.0.4 start,
|
215
|
+
stop, scan and prio is not implemented.\n\nThe test files live in the folder test
|
216
|
+
and start with test_.\n\nThere is a rake file available to run all tests\n\n $
|
217
|
+
rake test\n \n==License\nsyc-task is released under the {MIT License}[http://opensource.org/licenses/MIT]\n\n==Links\n*
|
218
|
+
[http://www.github.com/sugaryourcoffee/syc-task] - Source code on GitHub\n* [http://syc.dyndns.org/drupal/wiki/syc-task]
|
219
|
+
- Development notebook\n* [https://rubygems.org/gems/syc-backup] - RubyGems\n"
|
145
220
|
email: pierre@sugaryourcoffee.de
|
146
221
|
executables:
|
147
222
|
- syctask
|
@@ -162,6 +237,10 @@ files:
|
|
162
237
|
- lib/syctask/times.rb
|
163
238
|
- lib/syctask/schedule.rb
|
164
239
|
- lib/sycutil/console.rb
|
240
|
+
- lib/syctask/environment.rb
|
241
|
+
- lib/syctask/task_tracker.rb
|
242
|
+
- lib/syctime/time_util.rb
|
243
|
+
- lib/sycstring/string_util.rb
|
165
244
|
- README.rdoc
|
166
245
|
- syctask.rdoc
|
167
246
|
homepage: http://syc.dyndns.org/drupal/syc-task
|