doing 0.2.5pre → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -4
- data/bin/doing +80 -2
- data/lib/doing/version.rb +1 -1
- data/lib/doing/wwid.rb +70 -9
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a4645c47a272a4fdf45174b2adff019820ed1537
|
4
|
+
data.tar.gz: 444fa7c255629e9f9e5f1b357c28b0fd2ac3e8c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b8872bc854b897c25737f79f50ab86ec91f48b5b64118cc121c463c0782738070150b06ef8a9e076b5a9bdf5922f94a5d45db35166f80af8cf0fc63f9e51519
|
7
|
+
data.tar.gz: 4ed502a4de7165e67a5cc41d4737f069ececd82e64efa8af092d0c847b32ca1e99151ec7071945dace041277208411c0e0b36bdfc6a468330bb14a60b3660e87
|
data/README.md
CHANGED
@@ -261,6 +261,7 @@ Outputs:
|
|
261
261
|
now - Add an entry
|
262
262
|
later - Add an item to the Later section
|
263
263
|
done - Add a completed item with @done(date). No argument finishes last entry.
|
264
|
+
meanwhile - Finish any @meanwhile tasks and optionally create a new one
|
264
265
|
|
265
266
|
The `doing now` command can accept `-s section_name` to send the new entry straight to a non-default section.
|
266
267
|
|
@@ -270,6 +271,8 @@ You can also backdate entries using natural language with `--back 15m` or `--bac
|
|
270
271
|
|
271
272
|
All of these commands accept a `-e` argument. This opens your command line editor as defined in the environment variable `$EDITOR`. Add your entry, save the temp file and close it, and the new entry will be added. Anything after the first line is included as a note on the entry.
|
272
273
|
|
274
|
+
`doing meanwhile` is a special command for creating and finishing tasks that may have other entries come before they're complete. When you create an entry with `doing meanwhile [entry text]`, it will automatically complete the last @meanwhile item (dated @done tag) and add the @meanwhile tag to the new item. This allows time tracking on a more general basis, and still lets you keep track of the smaller things you do while working on an overarching project. The `meanwhile` command accepts `--back [time]` and will backdate the @done tag and start date of the new task at the same time. Running `meanwhile` with no arguments will simply complete the last @meanwhile task. See `doing help meanwhile` for more options.
|
275
|
+
|
273
276
|
#### Modifying entries:
|
274
277
|
|
275
278
|
finish - Mark last X entries as @done
|
@@ -285,10 +288,11 @@ All of these commands accept a `-e` argument. This opens your command line edito
|
|
285
288
|
|
286
289
|
#### Displaying entries:
|
287
290
|
|
288
|
-
show
|
289
|
-
recent
|
290
|
-
today
|
291
|
-
|
291
|
+
show - List all entries
|
292
|
+
recent - List recent entries
|
293
|
+
today - List entries from today
|
294
|
+
yesterday - List entries from yesterday
|
295
|
+
last - Show the last entry
|
292
296
|
|
293
297
|
`doing show` on its own will list all entries in the "Currently" section. Add a section name as an argument to display that section instead. Use "all" to display all entries from all sections.
|
294
298
|
|
@@ -300,6 +304,8 @@ The `show` command can also show the time spent on a task if it has a `@done(dat
|
|
300
304
|
|
301
305
|
If you have a use for it, you can use `--csv` on the show or view commands to output the results as a comma-separated CSV to STDOUT. Redirect to a file to save it: `doing show all done --csv > ~/Desktop/done.csv`.
|
302
306
|
|
307
|
+
`doing yesterday` is great for stand-ups, thanks to [Sean Collins](https://github.com/sc68cal) for that. Note that you can show yesterday's activity from an alternate section by using the section name as an argument (e.g. `doing yesterday archive`).
|
308
|
+
|
303
309
|
#### Views
|
304
310
|
|
305
311
|
view - Display a user-created view
|
data/bin/doing
CHANGED
@@ -25,6 +25,9 @@ switch [:notes], :default_value => true, :negatable => true
|
|
25
25
|
# desc 'Wrap notes at X chars (0 for no wrap)'
|
26
26
|
# flag [:w,:wrapwidth], :must_match => /^\d+$/, :type => Integer
|
27
27
|
|
28
|
+
desc 'Specify a different doing_file'
|
29
|
+
flag [:f, :doing_file]
|
30
|
+
|
28
31
|
desc 'Add an entry'
|
29
32
|
arg_name 'entry'
|
30
33
|
command :now do |c|
|
@@ -83,6 +86,53 @@ command :now do |c|
|
|
83
86
|
end
|
84
87
|
end
|
85
88
|
|
89
|
+
desc 'Finish any running @meanwhile tasks and optionally create a new one'
|
90
|
+
arg_name 'entry'
|
91
|
+
command :meanwhile do |c|
|
92
|
+
c.desc 'Section'
|
93
|
+
c.arg_name 'section_name'
|
94
|
+
c.default_value wwid.current_section
|
95
|
+
c.flag [:s,:section], :default_value => wwid.current_section
|
96
|
+
|
97
|
+
c.desc "Edit entry with #{ENV['EDITOR']}"
|
98
|
+
c.switch [:e,:editor]
|
99
|
+
|
100
|
+
c.desc "Archive previous @meanwhile entry"
|
101
|
+
c.switch [:a,:archive], :default_value => false
|
102
|
+
|
103
|
+
c.desc 'Backdate to "date_string" (natural language)'
|
104
|
+
c.flag [:back]
|
105
|
+
|
106
|
+
c.action do |global_options,options,args|
|
107
|
+
if options[:back]
|
108
|
+
date = wwid.chronify(options[:back])
|
109
|
+
|
110
|
+
raise "Unable to parse date string" if date.nil?
|
111
|
+
else
|
112
|
+
date = Time.now
|
113
|
+
end
|
114
|
+
|
115
|
+
section = wwid.guess_section(options[:s]) || options[:s].cap_first
|
116
|
+
input = ""
|
117
|
+
|
118
|
+
if options[:e]
|
119
|
+
raise "No EDITOR variable defined in environment" if ENV['EDITOR'].nil?
|
120
|
+
input += args.join(" ") if args.length > 0
|
121
|
+
input = wwid.fork_editor(input)
|
122
|
+
else
|
123
|
+
if args.length > 0
|
124
|
+
input = args.join(" ")
|
125
|
+
elsif STDIN.stat.size > 0
|
126
|
+
input = STDIN.read
|
127
|
+
end
|
128
|
+
end
|
129
|
+
input = false unless input && input.length > 0
|
130
|
+
|
131
|
+
wwid.stop_start("meanwhile",{:new_item => input, :back => date, :section => section, :archive => options[:a]})
|
132
|
+
wwid.write(wwid.doing_file)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
86
136
|
desc 'Add an item to the Later section'
|
87
137
|
arg_name 'entry'
|
88
138
|
command :later do |c|
|
@@ -136,6 +186,10 @@ end
|
|
136
186
|
desc 'Add a completed item with @done(date). No argument finishes last entry.'
|
137
187
|
arg_name 'entry'
|
138
188
|
command :done do |c|
|
189
|
+
c.desc 'Remove @done tag'
|
190
|
+
c.default_value false
|
191
|
+
c.switch [:r,:remove], :negatable => false, :default_value => false
|
192
|
+
|
139
193
|
c.desc 'Include date'
|
140
194
|
c.default_value true
|
141
195
|
c.switch [:d,:date], :default_value => true
|
@@ -185,7 +239,11 @@ command :done do |c|
|
|
185
239
|
raise "No content"
|
186
240
|
end
|
187
241
|
elsif args.length == 0 && STDIN.stat.size == 0
|
188
|
-
|
242
|
+
if options[:r]
|
243
|
+
wwid.tag_last({:tags => ["done"], :count => 1, :section => section, :remove => true })
|
244
|
+
else
|
245
|
+
wwid.tag_last({:tags => ["done"], :count => 1, :section => section, :archive => options[:a], :back => date, :date => options[:d]})
|
246
|
+
end
|
189
247
|
else
|
190
248
|
if args.length > 0
|
191
249
|
title, note = wwid.format_input(args.join(" "))
|
@@ -430,6 +488,16 @@ command :today do |c|
|
|
430
488
|
end
|
431
489
|
end
|
432
490
|
|
491
|
+
desc 'List entries from yesterday'
|
492
|
+
default_value wwid.current_section
|
493
|
+
arg_name 'section'
|
494
|
+
command :yesterday do |c|
|
495
|
+
c.action do |global_options, options,args|
|
496
|
+
section = args.length > 0 ? args.join(" ") : wwid.current_section
|
497
|
+
puts wwid.yesterday(section).strip
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
433
501
|
desc 'Show the last entry'
|
434
502
|
command :last do |c|
|
435
503
|
c.action do |global_options,options,args|
|
@@ -616,11 +684,16 @@ command :config do |c|
|
|
616
684
|
c.desc 'Application to use (OS X only)'
|
617
685
|
c.flag [:a]
|
618
686
|
|
687
|
+
c.desc "Use the editor_app defined in ~/.doingrc (#{wwid.config['editor_app']})"
|
688
|
+
c.switch [:x]
|
689
|
+
|
619
690
|
c.desc 'Application bundle id to use (OS X only)'
|
620
691
|
c.flag [:b]
|
621
692
|
|
622
693
|
c.action do |global_options,options,args|
|
623
|
-
if options[:
|
694
|
+
if options[:x]
|
695
|
+
%x{open -a "#{wwid.config['editor_app']}" "#{File.expand_path(DOING_CONFIG)}"}
|
696
|
+
elsif options[:a] || options[:b]
|
624
697
|
if options[:a]
|
625
698
|
%x{open -a "#{options[:a]}" "#{File.expand_path(DOING_CONFIG)}"}
|
626
699
|
elsif options[:b]
|
@@ -635,6 +708,11 @@ command :config do |c|
|
|
635
708
|
end
|
636
709
|
|
637
710
|
pre do |global,command,options,args|
|
711
|
+
if global[:doing_file]
|
712
|
+
wwid.init_doing_file(input=global[:doing_file])
|
713
|
+
else
|
714
|
+
wwid.init_doing_file
|
715
|
+
end
|
638
716
|
wwid.config[:include_notes] = false unless global[:notes]
|
639
717
|
if global[:version]
|
640
718
|
puts "doing v" + Doing::VERSION
|
data/lib/doing/version.rb
CHANGED
data/lib/doing/wwid.rb
CHANGED
@@ -12,7 +12,7 @@ class WWID
|
|
12
12
|
attr_accessor :content, :sections, :current_section, :doing_file, :config
|
13
13
|
|
14
14
|
|
15
|
-
def initialize
|
15
|
+
def initialize
|
16
16
|
@content = {}
|
17
17
|
@timers = {}
|
18
18
|
@config = read_config
|
@@ -64,7 +64,6 @@ class WWID
|
|
64
64
|
@config['marker_tag'] ||= 'flagged'
|
65
65
|
@config['marker_color'] ||= 'red'
|
66
66
|
|
67
|
-
@doing_file = File.expand_path(config['doing_file'])
|
68
67
|
@current_section = config['current_section']
|
69
68
|
@default_template = config['templates']['default']['template']
|
70
69
|
@default_date_format = config['templates']['default']['date_format']
|
@@ -72,17 +71,24 @@ class WWID
|
|
72
71
|
@config[:include_notes] ||= true
|
73
72
|
|
74
73
|
File.open(File.expand_path(DOING_CONFIG), 'w') { |yf| YAML::dump(config, yf) }
|
74
|
+
end
|
75
|
+
|
76
|
+
def init_doing_file(input=nil)
|
77
|
+
@doing_file = File.expand_path(config['doing_file'])
|
75
78
|
|
76
79
|
if input.nil?
|
77
80
|
create(@doing_file) unless File.exists?(@doing_file)
|
78
81
|
input = IO.read(@doing_file)
|
79
82
|
input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
|
80
83
|
elsif File.exists?(File.expand_path(input)) && File.file?(File.expand_path(input)) && File.stat(File.expand_path(input)).size > 0
|
84
|
+
@doing_file = File.expand_path(input)
|
81
85
|
input = IO.read(File.expand_path(input))
|
82
86
|
input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
|
83
|
-
@doing_file = File.expand_path(input)
|
84
87
|
elsif input.length < 256
|
88
|
+
@doing_file = File.expand_path(input)
|
85
89
|
create(input)
|
90
|
+
input = IO.read(File.expand_path(input))
|
91
|
+
input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
|
86
92
|
end
|
87
93
|
|
88
94
|
@other_content_top = []
|
@@ -125,7 +131,9 @@ class WWID
|
|
125
131
|
end
|
126
132
|
|
127
133
|
def create(filename=nil)
|
128
|
-
filename
|
134
|
+
if filename.nil?
|
135
|
+
filename = @doing_file
|
136
|
+
end
|
129
137
|
unless File.exists?(filename) && File.stat(filename).size > 0
|
130
138
|
File.open(filename,'w+') do |f|
|
131
139
|
f.puts @current_section + ":"
|
@@ -302,7 +310,7 @@ class WWID
|
|
302
310
|
title = item['title']
|
303
311
|
opt[:tags].each {|tag|
|
304
312
|
if opt[:remove]
|
305
|
-
title.gsub!(/(^| )@#{tag}
|
313
|
+
title.gsub!(/(^| )@#{tag.strip}(\([^\)]*\))?/,'')
|
306
314
|
else
|
307
315
|
unless title =~ /@#{tag}/
|
308
316
|
if (tag == "done" && opt[:date]) || opt[:date]
|
@@ -328,6 +336,43 @@ class WWID
|
|
328
336
|
end
|
329
337
|
end
|
330
338
|
|
339
|
+
# accepts one tag and the raw text of a new item
|
340
|
+
# if the passed tag is on any item, it's replaced with @done
|
341
|
+
# if new_item is not nil, it's tagged with the passed tag and inserted
|
342
|
+
# This is for use where only one instance of a given tag should exist (@meanwhile)
|
343
|
+
def stop_start(tag,opt={})
|
344
|
+
opt[:section] ||= @current_section
|
345
|
+
opt[:archive] ||= false
|
346
|
+
opt[:back] ||= Time.now
|
347
|
+
opt[:new_item] ||= false
|
348
|
+
|
349
|
+
opt[:section] = guess_section(opt[:section])
|
350
|
+
|
351
|
+
tag.sub!(/^@/,'')
|
352
|
+
|
353
|
+
@content[opt[:section]]['items'].each_with_index {|item, i|
|
354
|
+
if item['title'] =~ /@#{tag}/
|
355
|
+
title = item['title'].gsub(/(^| )@(#{tag}|done)(\([^\)]*\))?/,'')
|
356
|
+
title += " @done(#{opt[:back].strftime('%F %R')})"
|
357
|
+
|
358
|
+
@content[opt[:section]]['items'][i]['title'] = title
|
359
|
+
|
360
|
+
if opt[:archive] && opt[:section] != "Archive"
|
361
|
+
@content['Archive']['items'].push(@content[opt[:section]]['items'][i])
|
362
|
+
@content[opt[:section]]['items'].delete_at(i)
|
363
|
+
end
|
364
|
+
end
|
365
|
+
}
|
366
|
+
|
367
|
+
if opt[:new_item]
|
368
|
+
title, note = format_input(opt[:new_item])
|
369
|
+
title += " @#{tag}"
|
370
|
+
add_item(title.cap_first, opt[:section], {:note => note, :back => opt[:back]})
|
371
|
+
end
|
372
|
+
|
373
|
+
write(@doing_file)
|
374
|
+
end
|
375
|
+
|
331
376
|
def write(file=nil)
|
332
377
|
if @other_content_top.empty?
|
333
378
|
output = ""
|
@@ -448,6 +493,10 @@ class WWID
|
|
448
493
|
item['date'] < Date.today.to_time
|
449
494
|
}.reverse!
|
450
495
|
section = Time.now.strftime('%A, %B %d')
|
496
|
+
elsif opt[:yesterday]
|
497
|
+
items.delete_if {|item| item['date'] <= Date.today.prev_day.to_time or
|
498
|
+
item['date'] >= Date.today.to_time
|
499
|
+
}.reverse!
|
451
500
|
else
|
452
501
|
if opt[:age] =~ /oldest/i
|
453
502
|
items = items[0..count]
|
@@ -486,13 +535,20 @@ class WWID
|
|
486
535
|
# else
|
487
536
|
# note = ''
|
488
537
|
# end
|
538
|
+
if RUBY_VERSION.to_f > 1.8
|
539
|
+
title = i['title'].force_encoding('utf-8')
|
540
|
+
note = i['note'].map {|line| line.force_encoding('utf-8').strip } if i['note']
|
541
|
+
else
|
542
|
+
title = i['title']
|
543
|
+
note = i['note'].map { |line| line.strip }
|
544
|
+
end
|
489
545
|
items_out << {
|
490
546
|
:date => i['date'].strftime('%a %-I:%M%p'),
|
491
|
-
:title =>
|
492
|
-
:note =>
|
547
|
+
:title => title.gsub(/(@[^ \(]+(\(.*?\))?)/im,'<span class="tag">\1</span>').strip, #+ " #{note}"
|
548
|
+
:note => note
|
493
549
|
}
|
494
550
|
}
|
495
|
-
style = "body{background:#
|
551
|
+
style = "body{background:#fff;color:#333;font-family:Helvetica,arial,freesans,clean,sans-serif;font-size:16px;line-height:120%;text-align:justify;padding:20px}h1{text-align:left;position:relative;left:220px;margin-bottom:1em}ul{list-style-position:outside;position:relative;left:170px;margin-right:170px;text-align:left}ul li{list-style-type:none;border-left:solid 1px #ccc;padding-left:10px;line-height:2}ul li .date{font-size:14px;position:absolute;left:-82px;color:#7d9ca2;text-align:right;width:110px;line-height:2}ul li .tag{color:#999}ul li .note{display:block;color:#666;padding:0 0 0 22px;line-height:1.4;font-size:15px}ul li .note:before{content:'\\25BA';font-weight:300;position:absolute;left:40px;font-size:8px;color:#aaa;line-height:3}ul li:hover .note{display:block}"
|
496
552
|
template =<<EOT
|
497
553
|
!!!
|
498
554
|
%html
|
@@ -580,7 +636,7 @@ EOT
|
|
580
636
|
output.gsub!(/\s(@\S+(?:\(.*?\))?)/," #{colors[opt[:tags_color]]}\\1")
|
581
637
|
end
|
582
638
|
output.sub!(/%note/,note)
|
583
|
-
output.sub!(/%odnote/,note.gsub(
|
639
|
+
output.sub!(/%odnote/,note.gsub(/^\t*/,""))
|
584
640
|
output.gsub!(/%hr(_under)?/) do |m|
|
585
641
|
o = ""
|
586
642
|
`tput cols`.to_i.times do
|
@@ -736,6 +792,11 @@ EOT
|
|
736
792
|
list_section({:section => @current_section, :wrap_width => cfg['wrap_width'], :count => 0, :format => cfg['date_format'], :template => cfg['template'], :order => "asc", :today => true, :times => times, :output => output})
|
737
793
|
end
|
738
794
|
|
795
|
+
def yesterday(section)
|
796
|
+
section = guess_section(section)
|
797
|
+
list_section({:section => section, :count => 0, :order => "asc", :yesterday => true})
|
798
|
+
end
|
799
|
+
|
739
800
|
def recent(count=10,section=nil,opt={})
|
740
801
|
times = opt[:t] || true
|
741
802
|
cfg = @config['templates']['recent']
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: doing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -144,9 +144,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
144
144
|
version: '0'
|
145
145
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
146
|
requirements:
|
147
|
-
- - '
|
147
|
+
- - '>='
|
148
148
|
- !ruby/object:Gem::Version
|
149
|
-
version:
|
149
|
+
version: '0'
|
150
150
|
requirements: []
|
151
151
|
rubyforge_project:
|
152
152
|
rubygems_version: 2.2.2
|