gwtf 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/gwtf/commands/done_command.rb +1 -1
- data/lib/gwtf/commands/edit_command.rb +35 -21
- data/lib/gwtf/commands/list_command.rb +5 -4
- data/lib/gwtf/commands/new_command.rb +2 -2
- data/lib/gwtf/commands/open_command.rb +1 -3
- data/lib/gwtf/commands/remind_command.rb +57 -0
- data/lib/gwtf/commands/shell_command.rb +1 -2
- data/lib/gwtf/commands/show_command.rb +2 -35
- data/lib/gwtf/item.rb +62 -0
- data/lib/gwtf/items.rb +3 -3
- data/lib/gwtf/version.rb +1 -1
- metadata +5 -4
@@ -1,35 +1,49 @@
|
|
1
|
-
desc 'Edit an item using EDITOR'
|
2
|
-
arg_name '
|
1
|
+
desc 'Edit an item subject using pattern replacement of using EDITOR'
|
2
|
+
arg_name 'item'
|
3
|
+
arg_name 'item [/foo/bar]'
|
3
4
|
command [:edit, :vi, :e] do |c|
|
4
5
|
c.action do |global_options,options,args|
|
5
6
|
raise "Please specify an item ID to edit" if args.empty?
|
6
|
-
raise "EDITOR environment variable should be set" unless ENV.include?("EDITOR")
|
7
7
|
|
8
8
|
item = @items.load_item(args.first)
|
9
9
|
|
10
|
-
|
10
|
+
if args.size == 1
|
11
|
+
raise "EDITOR environment variable should be set" unless ENV.include?("EDITOR")
|
11
12
|
|
12
|
-
|
13
|
+
descr_sep = "== EDIT BETWEEN THESE LINES =="
|
13
14
|
|
14
|
-
|
15
|
-
tmp = Tempfile.new("gwtf")
|
16
|
-
tmp.write(temp_item.to_yaml)
|
17
|
-
tmp.rewind
|
18
|
-
system("%s %s" % [ENV["EDITOR"], tmp.path])
|
19
|
-
edited_item = YAML.load_file(tmp.path)
|
20
|
-
ensure
|
21
|
-
tmp.close
|
22
|
-
tmp.unlink
|
23
|
-
end
|
15
|
+
temp_item = {"description" => "#{descr_sep}\n#{item.description}\n#{descr_sep}", "subject" => item.subject}
|
24
16
|
|
25
|
-
|
17
|
+
begin
|
18
|
+
tmp = Tempfile.new("gwtf")
|
19
|
+
tmp.write(temp_item.to_yaml)
|
20
|
+
tmp.rewind
|
21
|
+
system("%s %s" % [ENV["EDITOR"], tmp.path])
|
22
|
+
edited_item = YAML.load_file(tmp.path)
|
23
|
+
ensure
|
24
|
+
tmp.close
|
25
|
+
tmp.unlink
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
item.subject = edited_item["subject"] if edited_item["subject"]
|
29
|
+
|
30
|
+
if edited_item["description"] =~ /#{descr_sep}\n(.+)\n#{descr_sep}/m
|
31
|
+
item.description = $1
|
32
|
+
end
|
30
33
|
|
31
|
-
|
34
|
+
item.save
|
32
35
|
|
33
|
-
|
36
|
+
puts item
|
37
|
+
else
|
38
|
+
editor = args[1..-1].join(" ")
|
39
|
+
delim = editor[0,1]
|
40
|
+
splits = editor.split(delim)
|
41
|
+
|
42
|
+
raise "Attempting to do a subject edit with #{editor} based on delimiter #{delim} failed" unless splits.size == 3
|
43
|
+
|
44
|
+
item.subject = item.subject.gsub(splits[1], splits[2])
|
45
|
+
item.save
|
46
|
+
puts item
|
47
|
+
end
|
34
48
|
end
|
35
49
|
end
|
@@ -10,14 +10,15 @@ command [:list, :ls, :l] do |c|
|
|
10
10
|
@items.each_item do |item|
|
11
11
|
count[ item[:status] ] += 1
|
12
12
|
|
13
|
-
|
13
|
+
flags = []
|
14
|
+
flags << "D" if item.has_description?
|
15
|
+
flags << "C" if item.closed? && options[:all]
|
14
16
|
|
15
|
-
puts "%5s %-
|
16
|
-
puts "%5s %-3s%8s" % [ id, "C", item.subject] if (item.closed? && options[:all])
|
17
|
+
puts "%5s %-4s%-12s%8s" % [ item.item_id, flags.join, Time.parse(item.created_at).strftime("%F"), item.subject ] if (options[:all] || item.open?)
|
17
18
|
end
|
18
19
|
|
19
20
|
puts
|
20
|
-
puts "
|
21
|
+
puts "Project %s items: %d / %d" % [ global_options[:project], count["open"], count["open"] + count["closed"] ]
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
desc 'Create an item'
|
2
2
|
arg_name 'Short item description'
|
3
|
-
command [:new, :n] do |c|
|
3
|
+
command [:new, :add, :n, :a, :c] do |c|
|
4
4
|
c.desc 'Invoke EDITOR to provide a long form description'
|
5
5
|
c.default_value false
|
6
6
|
c.switch [:edit, :e]
|
@@ -26,6 +26,6 @@ command [:new, :n] do |c|
|
|
26
26
|
item.description = description if description
|
27
27
|
item.save
|
28
28
|
|
29
|
-
puts
|
29
|
+
puts item
|
30
30
|
end
|
31
31
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
desc 'Send a reminder about an item via email'
|
2
|
+
arg_name 'id [at time specification]'
|
3
|
+
long_desc <<EOF
|
4
|
+
When run without the --send option this comand will
|
5
|
+
add an at() job using the supplied at time specification.
|
6
|
+
|
7
|
+
The at job will call the same command again this time
|
8
|
+
with the --send option that will send an email to you
|
9
|
+
or the address specified in --recipient using your system
|
10
|
+
mail command
|
11
|
+
EOF
|
12
|
+
|
13
|
+
command [:remind, :rem] do |c|
|
14
|
+
c.desc 'Email address to send to'
|
15
|
+
c.default_value Etc.getlogin
|
16
|
+
c.flag [:recipient, :r]
|
17
|
+
|
18
|
+
c.desc 'Send email immediately'
|
19
|
+
c.default_value false
|
20
|
+
c.switch [:send]
|
21
|
+
|
22
|
+
c.action do |global_options,options,args|
|
23
|
+
raise "Please supply an item ID to remind about" if args.empty?
|
24
|
+
|
25
|
+
unless options[:send]
|
26
|
+
raise "Please specify a valid at() time specification" unless args.size > 2
|
27
|
+
|
28
|
+
at = args[1..-1].join(" ")
|
29
|
+
|
30
|
+
STDOUT.sync
|
31
|
+
|
32
|
+
print "Creating reminder at job for item #{args.first}: "
|
33
|
+
system "echo gwtf --project='%s' remind --recipient='%s' --send %s|at %s" % [ global_options[:project], options[:recipient], args.first, at]
|
34
|
+
else
|
35
|
+
item = @items.load_item(args.first)
|
36
|
+
|
37
|
+
begin
|
38
|
+
tmp = Tempfile.new("gwtf")
|
39
|
+
tmp.write(item.summary)
|
40
|
+
tmp.rewind
|
41
|
+
|
42
|
+
if global_options[:project] == "default"
|
43
|
+
subject = "Reminder for item %s" % [ args.first ]
|
44
|
+
else
|
45
|
+
subject = "Reminder for item %s in %s project" % [ args.first, global_options[:project] ]
|
46
|
+
end
|
47
|
+
|
48
|
+
system("cat #{tmp.path}|mail -s '#{subject}' '#{options[:recipient]}'")
|
49
|
+
ensure
|
50
|
+
tmp.close
|
51
|
+
tmp.unlink
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
@@ -30,13 +30,12 @@ command :shell do |c|
|
|
30
30
|
end
|
31
31
|
|
32
32
|
description = "Worked in a subshell" if description == ""
|
33
|
-
description = description + " (#{Gwtf.seconds_to_human(elapsed_time.round)})"
|
34
33
|
|
35
34
|
item.record_work(description, elapsed_time.round)
|
36
35
|
|
37
36
|
item.save
|
38
37
|
|
39
|
-
puts "Recorded #{elapsed_time}
|
38
|
+
puts "Recorded #{Gwtf.seconds_to_human(elapsed_time.round)} of work against item: #{item}"
|
40
39
|
end
|
41
40
|
end
|
42
41
|
|
@@ -1,44 +1,11 @@
|
|
1
1
|
desc 'Show an item'
|
2
|
-
arg_name '
|
2
|
+
arg_name 'id'
|
3
3
|
command [:show, :s] do |c|
|
4
4
|
c.action do |global_options,options,args|
|
5
5
|
raise "Please supply an item ID to show" if args.empty?
|
6
6
|
|
7
7
|
item = @items.load_item(args.first)
|
8
8
|
|
9
|
-
|
10
|
-
begin
|
11
|
-
result + log["elapsed"]
|
12
|
-
rescue
|
13
|
-
result
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
puts " ID: %s" % [ item.item_id ]
|
18
|
-
puts " Subject: %s" % [ item.subject ]
|
19
|
-
puts " Status: %s" % [ item.status ]
|
20
|
-
puts "Time Worked: %s" % [ Gwtf.seconds_to_human(time_worked) ]
|
21
|
-
puts " Created: %s" % [ Time.parse(item.created_at).strftime("%D %R") ]
|
22
|
-
puts " Closed: %s" % [ Time.parse(item.closed_at).strftime("%D %R") ] if item.closed?
|
23
|
-
|
24
|
-
if item.has_description?
|
25
|
-
puts
|
26
|
-
puts "Description:"
|
27
|
-
|
28
|
-
item.description.split("\n").each do |line|
|
29
|
-
puts "%13s%s" % [ "", line]
|
30
|
-
end
|
31
|
-
|
32
|
-
puts
|
33
|
-
end
|
34
|
-
|
35
|
-
time_spent = 0
|
36
|
-
|
37
|
-
item.work_log.each_with_index do |log, idx|
|
38
|
-
puts
|
39
|
-
puts "Work Log: " if idx == 0
|
40
|
-
|
41
|
-
puts "%27s %s" % [Time.parse(log["time"]).strftime("%D %R"), log["text"]]
|
42
|
-
end
|
9
|
+
puts item.summary
|
43
10
|
end
|
44
11
|
end
|
data/lib/gwtf/item.rb
CHANGED
@@ -56,6 +56,68 @@ module Gwtf
|
|
56
56
|
"work_log" => []}
|
57
57
|
end
|
58
58
|
|
59
|
+
def time_worked
|
60
|
+
work_log.inject(0) do |result, log|
|
61
|
+
begin
|
62
|
+
result + log["elapsed"]
|
63
|
+
rescue
|
64
|
+
result
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def flags
|
70
|
+
flag = []
|
71
|
+
|
72
|
+
flag << "closed" if closed?
|
73
|
+
flag << "open" if open?
|
74
|
+
flag << "descr" if description?
|
75
|
+
flag << work_log.size.to_s unless work_log.empty?
|
76
|
+
flag
|
77
|
+
end
|
78
|
+
|
79
|
+
def summary
|
80
|
+
summary = StringIO.new
|
81
|
+
|
82
|
+
summary.puts " Subject: %s" % [ subject ]
|
83
|
+
summary.puts " Status: %s" % [ status ]
|
84
|
+
summary.puts "Time Worked: %s" % [ Gwtf.seconds_to_human(time_worked) ]
|
85
|
+
summary.puts " Created: %s" % [ Time.parse(created_at).strftime("%F %R") ]
|
86
|
+
summary.puts " Closed: %s" % [ Time.parse(closed_at).strftime("%F %R") ] if closed?
|
87
|
+
summary.puts " ID: %s" % [ item_id ]
|
88
|
+
|
89
|
+
if has_description?
|
90
|
+
summary.puts
|
91
|
+
summary.puts "Description:"
|
92
|
+
|
93
|
+
description.split("\n").each do |line|
|
94
|
+
summary.puts "%13s%s" % [ "", line]
|
95
|
+
end
|
96
|
+
|
97
|
+
summary.puts
|
98
|
+
end
|
99
|
+
|
100
|
+
time_spent = 0
|
101
|
+
|
102
|
+
work_log.reverse.each_with_index do |log, idx|
|
103
|
+
summary.puts if idx == 0
|
104
|
+
summary.puts "Work Log: " if idx == 0
|
105
|
+
|
106
|
+
# we used to automatically embed this into the description which was dumb
|
107
|
+
elapsed = "(%s)" % [Gwtf.seconds_to_human(log["elapsed"])] unless log["text"] =~ /\(.+?\)$/
|
108
|
+
|
109
|
+
summary.puts "%27s %s %s" % [Time.parse(log["time"]).strftime("%F %R"), log["text"], elapsed]
|
110
|
+
end
|
111
|
+
|
112
|
+
summary.string
|
113
|
+
end
|
114
|
+
|
115
|
+
def to_s
|
116
|
+
flag = " (#{flags.join(',')})" unless flags.empty?
|
117
|
+
|
118
|
+
"%s%s: %s" % [item_id, flag, subject]
|
119
|
+
end
|
120
|
+
|
59
121
|
def to_hash
|
60
122
|
@item
|
61
123
|
end
|
data/lib/gwtf/items.rb
CHANGED
@@ -56,8 +56,8 @@ module Gwtf
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
def
|
60
|
-
Dir.entries(@data_dir).grep(/\.gwtf$/).
|
59
|
+
def item_ids
|
60
|
+
Dir.entries(@data_dir).grep(/\.gwtf$/).map{|i| File.basename(i, ".gwtf")}.map{|i| Integer(i)}.sort
|
61
61
|
end
|
62
62
|
|
63
63
|
def file_for_item(item)
|
@@ -65,7 +65,7 @@ module Gwtf
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def each_item
|
68
|
-
|
68
|
+
item_ids.each {|item| yield load_item(item) }
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
data/lib/gwtf/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gwtf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- R.I.Pienaar
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-03-
|
18
|
+
date: 2012-03-12 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -94,6 +94,7 @@ files:
|
|
94
94
|
- lib/gwtf/commands/edit_command.rb
|
95
95
|
- lib/gwtf/commands/new_command.rb
|
96
96
|
- lib/gwtf/commands/list_command.rb
|
97
|
+
- lib/gwtf/commands/remind_command.rb
|
97
98
|
- lib/gwtf/version.rb
|
98
99
|
- lib/gwtf/item.rb
|
99
100
|
- lib/gwtf/items.rb
|