syc-task 0.0.4 → 0.0.6
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.
- 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
|