gwtf 0.1.0 → 0.2.0
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/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
|