doing 0.2.5pre → 0.2.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8806f026f8106baa4c033a2d30675e0f3c30afea
4
- data.tar.gz: 77139cb8ae62cc18311d5fcd7c27a725806375c9
3
+ metadata.gz: a4645c47a272a4fdf45174b2adff019820ed1537
4
+ data.tar.gz: 444fa7c255629e9f9e5f1b357c28b0fd2ac3e8c3
5
5
  SHA512:
6
- metadata.gz: 6fb8b55cc46ceefe4c139af635417b2c318e90705ef7da3fb3aa2e2050bd7e7de89d4d9633e538ec0ca26e6d3582a81e3fa394ac3bf032684d463a36573f5cca
7
- data.tar.gz: 659c26db54235f3ca7d13cc34bdc2f4cdd3e028cc6514c2c5f01c0c9216c7c0fcc693de629f3b965dd5b533e91b8390e09fdd29aebd010d5109ba947394ef16a
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 - List all entries
289
- recent - List recent entries
290
- today - List entries from today
291
- last - Show the last entry
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
- wwid.tag_last({:tags => ["done"], :count => 1, :section => section, :archive => options[:a], :back => date, :date => options[:d]})
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[:a] || options[:b]
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
@@ -1,3 +1,3 @@
1
1
  module Doing
2
- VERSION = '0.2.5pre'
2
+ VERSION = '0.2.5'
3
3
  end
@@ -12,7 +12,7 @@ class WWID
12
12
  attr_accessor :content, :sections, :current_section, :doing_file, :config
13
13
 
14
14
 
15
- def initialize(input=nil)
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 = @doing_file
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 => i['title'].gsub(/(@[^ \(]+(\(.*?\))?)/is,'<span class="tag">\1</span>').strip, #+ " #{note}"
492
- :note => i['note']
547
+ :title => title.gsub(/(@[^ \(]+(\(.*?\))?)/im,'<span class="tag">\1</span>').strip, #+ " #{note}"
548
+ :note => note
493
549
  }
494
550
  }
495
- style = "body{background:#faf9f5;color:#333;font-family:Palatino,Georgia,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:1.75}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}"
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(/\t\t/,"\t"))
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.5pre
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-03-22 00:00:00.000000000 Z
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: 1.3.1
149
+ version: '0'
150
150
  requirements: []
151
151
  rubyforge_project:
152
152
  rubygems_version: 2.2.2