timetrap 1.10.0 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2f0cfbd1ca2273c6fbcaa8a48af329f8bb02e29b
4
- data.tar.gz: 55d18f5690cfcfbf6f5379f244e323d5f2da4d80
3
+ metadata.gz: 271617ba22c6a444786172a06c319c130e520e3e
4
+ data.tar.gz: 58a80a95272541cf095d4727e580a1feda1b49f4
5
5
  SHA512:
6
- metadata.gz: 099d87442198a0dd457bf1ea35c6a2a7dd390b0b6c3935f63edfd6d5bb76d0adb605e82c46a454f1b5ff8e3bc36933c230267838050d2d311fac9a28ea776bfa
7
- data.tar.gz: 4e18a20f8a8cdff882cf3a2b72f4e31f5adb8af5b5f2aed738f649e2a5190c0028cbff9a40649bedd6cfa15587524633fc7763d7e292a71fbdc85575a0226654
6
+ metadata.gz: 75ac29be79462ac44122fedbe8255b48091d749cd08eed5ef672327c7d1a8e949f40ffdb584d3a203e2a3a42ea4ff0ef2ba81ca13c25477555e5d0d96556d409
7
+ data.tar.gz: d85f15fd101a3a3a321b2d6283c744ac1f7fdc919ee292a8366ad71543841fb70253c2274b8bbd691fae9ef6ac260386e51adf23c1b22fd344b6e287ed989dfb
@@ -2,3 +2,4 @@ language: ruby
2
2
  rvm:
3
3
  - 2.1.8
4
4
  - 2.2.4
5
+ - 2.3.1
@@ -13,3 +13,4 @@
13
13
  * Miles Matthias
14
14
  * Devon Blandin (@dblandin)
15
15
  * Marc Addeo
16
+ * Patrick Davey
data/README.md CHANGED
@@ -301,7 +301,7 @@ Commands
301
301
  Archives the selected entries (by moving them to a sheet called ``_[SHEET]``)
302
302
  These entries can be seen by running ``t display _[SHEET]``.
303
303
 
304
- usage: ``t archive [--start DATE] [--end DATE] [SHEET]``
304
+ usage: ``t archive [--start DATE] [--end DATE] [--grep REGEX] [SHEET]``
305
305
 
306
306
  **backend**
307
307
  Run an interactive database session on the timetrap database. Requires the
@@ -331,7 +331,7 @@ Commands
331
331
  Display also allows the use of a ``--round`` or ``-r`` flag which will round
332
332
  all times in the output. See global options below.
333
333
 
334
- usage: ``t display [--ids] [--round] [--start DATE] [--end DATE] [--format FMT] [SHEET | all | full]``
334
+ usage: ``t display [--ids] [--round] [--start DATE] [--end DATE] [--format FMT] [--grep REGEX] [SHEET | all | full]``
335
335
 
336
336
  **edit**
337
337
  Inserts a note associated with the an entry in the timesheet, or edits the
@@ -454,6 +454,11 @@ See ``t configure`` for details. Currently supported options are:
454
454
  **auto_sheet_search_paths**: an array of directories to search for user
455
455
  defined auto_sheet classes
456
456
 
457
+ **note_editor**: The command to start editing notes. Defaults to false which
458
+ means no external editor is used. Please see the section below
459
+ on Notes Editing for tips on using non-terminal based editors.
460
+ Example: note_editor: "vim"
461
+
457
462
 
458
463
  ### Autocomplete
459
464
 
@@ -494,6 +499,17 @@ Then add this to source the completions:
494
499
  fpath=(/path/to/timetrap-1.x.y/gem/completions/zsh $fpath)
495
500
  ```
496
501
 
502
+ #### Notes editing
503
+ If you use the note_editor setting, then it is possible to use
504
+ an editor for writing your notes. If you use a non terminal based
505
+ editor (like atom, sublime etc.) then you will need to make timetrap
506
+ wait until the editor has finished. If you're using the "core.editor"
507
+ flag in git, then it'll be the same flags you'll use.
508
+
509
+ As of when this command was added, for atom you would use `atom --wait`
510
+ and for sublime `subl -w`. If you use a console based editor (vim, emacs,
511
+ nano) then it should just work.
512
+
497
513
  Special Thanks
498
514
  --------------
499
515
 
@@ -1,6 +1,7 @@
1
1
  require "rubygems"
2
2
 
3
3
  require 'chronic'
4
+ require 'tempfile'
4
5
  require 'sequel'
5
6
  require 'yaml'
6
7
  require 'erb'
@@ -42,6 +42,9 @@ COMMAND is one of:
42
42
  you check in or out
43
43
  require_note: Prompt for a note if one isn't provided when
44
44
  checking in
45
+ note_editor: Command to launch notes editor or false if no editor use.
46
+ If you use a non terminal based editor (e.g. sublime, atom)
47
+ please read the notes in the README.
45
48
 
46
49
  * display - Display the current timesheet or a specific. Pass `all' as SHEET
47
50
  to display all unarchived sheets or `full' to display archived and
@@ -74,7 +77,7 @@ COMMAND is one of:
74
77
 
75
78
  * kill - Delete a timesheet or an entry.
76
79
  usage: t kill [--id ID] [TIMESHEET]
77
- -i, --id <id:i> Alter entry with id <id> instead of the running entry
80
+ -i, --id <id:i> Delete entry with id <id> instead of timesheet
78
81
 
79
82
  * list - Show the available timesheets.
80
83
  usage: t list
@@ -239,15 +242,24 @@ COMMAND is one of:
239
242
  entry.update :sheet => args['-m']
240
243
  end
241
244
 
242
- # update notes
243
- if unused_args =~ /.+/
244
- note = unused_args
245
+ if Config['note_editor']
245
246
  if args['-z']
246
- note = [entry.note, note].join(Config['append_notes_delimiter'])
247
+ note = [entry.note, get_note_from_external_editor].join(Config['append_notes_delimiter'])
248
+ entry.update :note => note
249
+ elsif args.size == 0 # no arguments supplied
250
+ entry.update :note => get_note_from_external_editor(entry.note)
251
+ end
252
+ else
253
+ if unused_args =~ /.+/
254
+ note = unused_args
255
+ if args['-z']
256
+ note = [entry.note, note].join(Config['append_notes_delimiter'])
257
+ end
258
+ entry.update :note => note
247
259
  end
248
- entry.update :note => note
249
260
  end
250
261
 
262
+
251
263
  puts format_entries(entry)
252
264
  end
253
265
 
@@ -262,12 +274,17 @@ COMMAND is one of:
262
274
  end
263
275
  end
264
276
 
277
+ note = unused_args
265
278
  if Config['require_note'] && !Timer.running? && unused_args.empty?
266
- $stderr.print("Please enter a note for this entry:\n> ")
267
- self.unused_args = $stdin.gets
279
+ if Config['note_editor']
280
+ note = get_note_from_external_editor
281
+ else
282
+ $stderr.print("Please enter a note for this entry:\n> ")
283
+ note = $stdin.gets.strip
284
+ end
268
285
  end
269
286
 
270
- Timer.start unused_args, args['-a']
287
+ Timer.start note, args['-a']
271
288
  warn "Checked into sheet #{Timer.current_sheet.inspect}."
272
289
  end
273
290
 
@@ -453,6 +470,21 @@ COMMAND is one of:
453
470
  $stdin.gets =~ /\Aye?s?\Z/i
454
471
  end
455
472
 
473
+ def get_note_from_external_editor(contents = "")
474
+ file = Tempfile.new('get_note')
475
+ unless contents.empty?
476
+ file.open
477
+ file.write(contents)
478
+ file.close
479
+ end
480
+
481
+ system("#{Config['note_editor']} #{file.path}")
482
+ file.open.read
483
+ ensure
484
+ file.close
485
+ file.unlink
486
+ end
487
+
456
488
  extend Helpers::AutoLoad
457
489
  def format_entries(entries)
458
490
  load_formatter(args['-f'] || Config['default_formatter']).new(Array(entries)).output
@@ -35,7 +35,9 @@ module Timetrap
35
35
  # automatically check out of any running tasks when checking in.
36
36
  'auto_checkout' => false,
37
37
  # interactively prompt for a note if one isn't passed when checking in.
38
- 'require_note' => false
38
+ 'require_note' => false,
39
+ # command to launch external editor (false if no external editor used)
40
+ 'note_editor' => false
39
41
  }
40
42
  end
41
43
 
@@ -1,22 +1,19 @@
1
1
  module Timetrap
2
2
  module Formatters
3
3
  class Text
4
+ LONGEST_NOTE_LENGTH = 50
4
5
  attr_accessor :output
5
6
  include Timetrap::Helpers
6
7
 
7
8
  def initialize entries
9
+ @entries = entries
8
10
  self.output = ''
9
11
  sheets = entries.inject({}) do |h, e|
10
12
  h[e.sheet] ||= []
11
13
  h[e.sheet] << e
12
14
  h
13
15
  end
14
- longest_note = entries.inject('Notes'.length) {|l, e| [e.note.to_s.rstrip.length, l].max}
15
- max_id_length = if Timetrap::CLI.args['-v']
16
- entries.inject(3) {|l, e| [e.id.to_s.length, l].max}
17
- else
18
- 3
19
- end
16
+
20
17
  (sheet_names = sheets.keys.sort).each do |sheet|
21
18
 
22
19
  self.output << "Timesheet: #{sheet}\n"
@@ -25,7 +22,6 @@ module Timetrap
25
22
  last_start = nil
26
23
  from_current_day = []
27
24
 
28
-
29
25
  sheets[sheet].each_with_index do |e, i|
30
26
  from_current_day << e
31
27
  self.output << "%-#{max_id_length + 1}s%16s%11s -%9s%10s %s\n" % [
@@ -34,7 +30,7 @@ module Timetrap
34
30
  format_time(e.start),
35
31
  format_time(e.end),
36
32
  format_duration(e.duration),
37
- e.note
33
+ format_note(e.note)
38
34
  ]
39
35
 
40
36
  nxt = sheets[sheet].to_a[i+1]
@@ -53,7 +49,53 @@ module Timetrap
53
49
  self.output << "%s\n" % ('-'*(4+52+longest_note))
54
50
  self.output << "Grand Total%41s\n" % format_total(sheets.values.flatten)
55
51
  end
52
+
53
+
54
+ end
55
+
56
+
57
+ private
58
+
59
+ attr_reader :entries
60
+
61
+ def longest_note
62
+ @longest_note ||= begin
63
+ entries.inject('Notes'.length) {|l, e| [e.note.to_s.rstrip.length, LONGEST_NOTE_LENGTH].min}
64
+ end
56
65
  end
66
+
67
+ def max_id_length
68
+ @max_id_length ||= begin
69
+ if Timetrap::CLI.args['-v']
70
+ entries.inject(3) {|l, e| [e.id.to_s.length, l].max}
71
+ else
72
+ 3
73
+ end
74
+ end
75
+ end
76
+
77
+ def format_note(note)
78
+ return "" unless note
79
+
80
+ lines = []
81
+ line_number = 0
82
+ note.lines.each do |line|
83
+ while index = line.index(/\s/, LONGEST_NOTE_LENGTH) do
84
+ shorter_line = line.slice!(0..(index - 1))
85
+ lines << padded_line(shorter_line.strip, line_number)
86
+ line_number += 1
87
+ end
88
+ lines << padded_line(line.strip, line_number)
89
+ line_number += 1
90
+ end
91
+ lines.join("\n")
92
+ end
93
+
94
+ def padded_line(content, line_number)
95
+ return content if line_number == 0
96
+ "#{" " * (56 + max_id_length - 3) }#{content}"
97
+ end
98
+
57
99
  end
58
100
  end
59
101
  end
@@ -1,3 +1,3 @@
1
1
  module Timetrap
2
- VERSION = '1.10.0'
2
+ VERSION = '1.11.0'
3
3
  end
@@ -3,6 +3,18 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'timetra
3
3
  require 'rspec'
4
4
  require 'fakefs/safe'
5
5
 
6
+ RSpec.configure do |config|
7
+ # as we are stubbing stderr and stdout, if you want to capture
8
+ # any of your output in tests, simply add :write_stdout_stderr => true
9
+ # as metadata to the end of your test
10
+ config.after(:each, write_stdout_stderr: true) do
11
+ $stderr.rewind
12
+ $stdout.rewind
13
+ File.write("stderr.txt", $stderr.read)
14
+ File.write("stdout.txt", $stdout.read)
15
+ end
16
+ end
17
+
6
18
  def local_time(str)
7
19
  Timetrap::Timer.process_time(str)
8
20
  end
@@ -14,7 +26,7 @@ end
14
26
  module Timetrap::StubConfig
15
27
  def with_stubbed_config options = {}
16
28
  defaults = Timetrap::Config.defaults.dup
17
- Timetrap::Config.stub(:[]).and_return do |k|
29
+ Timetrap::Config.stub(:[]) do |k|
18
30
  defaults.merge(options)[k]
19
31
  end
20
32
  yield if block_given?
@@ -129,9 +141,9 @@ describe Timetrap do
129
141
  FileUtils.mkdir_p(ENV['HOME'])
130
142
  config_file = ENV['HOME'] + '/.timetrap.yml'
131
143
  FileUtils.rm(config_file) if File.exist? config_file
132
- File.exist?(config_file).should be_false
144
+ File.exist?(config_file).should be_falsey
133
145
  invoke "configure"
134
- File.exist?(config_file).should be_true
146
+ File.exist?(config_file).should be_truthy
135
147
  end
136
148
  end
137
149
 
@@ -232,12 +244,63 @@ describe Timetrap do
232
244
  not_running.refresh.sheet.should == 'default'
233
245
  Timetrap::Timer.current_sheet.should == 'another second sheet'
234
246
  end
247
+
248
+ context "with external editor" do
249
+ let(:note_editor_command) { 'vim' }
250
+
251
+ before do
252
+ with_stubbed_config 'note_editor' => note_editor_command, 'append_notes_delimiter' => '//'
253
+ end
254
+
255
+ it "should open an editor for editing the note" do |example|
256
+ Timetrap::CLI.stub(:system) do |editor_command|
257
+ path = editor_command.match(/#{note_editor_command} (?<path>.*)/)
258
+ File.write(path[:path], "edited note")
259
+ end
260
+ Timetrap::Timer.active_entry.note.should == 'running entry'
261
+ invoke "edit"
262
+ Timetrap::Timer.active_entry.note.should == 'edited note'
263
+ end
264
+
265
+ it "should pass existing note to editor" do |example|
266
+ capture = nil
267
+ Timetrap::CLI.stub(:system) do |editor_command|
268
+ path = editor_command.match(/#{note_editor_command} (?<path>.*)/)
269
+
270
+ capture = File.read(path[:path])
271
+ end
272
+ invoke "edit"
273
+ expect(capture).to eq("running entry")
274
+ end
275
+
276
+ context "appending" do
277
+ it "should open an editor for editing the note with -z" do |example|
278
+ Timetrap::CLI.stub(:system) do |editor_command|
279
+ path = editor_command.match(/#{note_editor_command} (?<path>.*)/)
280
+ File.write(path[:path], "appended in editor")
281
+ end
282
+ Timetrap::Timer.active_entry.note.should == 'running entry'
283
+ invoke "edit -z"
284
+ Timetrap::Timer.active_entry.note.should == 'running entry//appended in editor'
285
+ end
286
+
287
+ it "should open a editor for editing the note with --append" do |example|
288
+ Timetrap::CLI.stub(:system) do |editor_command|
289
+ path = editor_command.match(/#{note_editor_command} (?<path>.*)/)
290
+ File.write(path[:path], "appended in editor")
291
+ end
292
+ Timetrap::Timer.active_entry.note.should == 'running entry'
293
+ invoke "edit --append"
294
+ Timetrap::Timer.active_entry.note.should == 'running entry//appended in editor'
295
+ end
296
+ end
297
+ end
235
298
  end
236
299
 
237
300
  describe 'auto_sheet' do
238
301
  describe "using dotfiles auto_sheet" do
239
302
  describe 'with a .timetrap-sheet in cwd' do
240
- it 'should use sheet defined in dorfile' do
303
+ it 'should use sheet defined in dotfile' do
241
304
  Dir.chdir('spec/dotfile') do
242
305
  with_stubbed_config('auto_sheet' => 'dotfiles')
243
306
  Timetrap::Timer.current_sheet.should == 'dotfile-sheet'
@@ -357,6 +420,12 @@ The "format" command is deprecated in favor of "display". Sorry for the inconven
357
420
  Timetrap::Entry.create( :sheet => 'SpecSheet',
358
421
  :note => 'entry 4', :start => '2008-10-05 18:00:00'
359
422
  )
423
+ Timetrap::Entry.create( :sheet => 'LongNoteSheet',
424
+ :note => "long notesheet " * 20, :start => '2008-10-05 16:00:00', :end => '2008-10-05 18:00:00'
425
+ )
426
+ Timetrap::Entry.create( :sheet => 'SheetWithLineBreakNote',
427
+ :note => "first line\nand a second line ", :start => '2008-10-05 16:00:00', :end => '2008-10-05 18:00:00'
428
+ )
360
429
 
361
430
  now = local_time('2008-10-05 20:00:00')
362
431
  Time.stub(:now).and_return now
@@ -410,26 +479,42 @@ Id Day Start End Duration Notes
410
479
  Total 8:00:00
411
480
  OUTPUT
412
481
 
413
- @desired_output_for_all = <<-OUTPUT
414
- Timesheet: SpecSheet
482
+ @desired_output_for_long_note_sheet = <<-OUTPUT
483
+ Timesheet: LongNoteSheet
415
484
  Day Start End Duration Notes
416
- Fri Oct 03, 2008 12:00:00 - 14:00:00 2:00:00 entry 1
417
- 16:00:00 - 18:00:00 2:00:00 entry 2
418
- 4:00:00
419
- Sun Oct 05, 2008 16:00:00 - 18:00:00 2:00:00 entry 3
420
- 18:00:00 - 2:00:00 entry 4
421
- 4:00:00
422
- ---------------------------------------------------------------------
423
- Total 8:00:00
485
+ Sun Oct 05, 2008 16:00:00 - 18:00:00 2:00:00 long notesheet long notesheet long notesheet long notesheet
486
+ long notesheet long notesheet long notesheet long
487
+ notesheet long notesheet long notesheet long notesheet
488
+ long notesheet long notesheet long notesheet long
489
+ notesheet long notesheet long notesheet long notesheet
490
+ long notesheet long notesheet
491
+ 2:00:00
492
+ ------------------------------------------------------------------------------------------------------
493
+ Total 2:00:00
494
+ OUTPUT
495
+
496
+ @desired_output_for_long_note_sheet_with_ids = <<-OUTPUT
497
+ Timesheet: LongNoteSheet
498
+ Id Day Start End Duration Notes
499
+ 60000 Sun Oct 05, 2008 16:00:00 - 18:00:00 2:00:00 long notesheet long notesheet long notesheet long notesheet
500
+ long notesheet long notesheet long notesheet long
501
+ notesheet long notesheet long notesheet long notesheet
502
+ long notesheet long notesheet long notesheet long
503
+ notesheet long notesheet long notesheet long notesheet
504
+ long notesheet long notesheet
505
+ 2:00:00
506
+ ------------------------------------------------------------------------------------------------------
507
+ Total 2:00:00
508
+ OUTPUT
424
509
 
425
- Timesheet: another
510
+ @desired_output_for_note_with_linebreak = <<-OUTPUT
511
+ Timesheet: SheetWithLineBreakNote
426
512
  Day Start End Duration Notes
427
- Sun Oct 05, 2008 18:00:00 - 2:00:00 a long entry note
513
+ Sun Oct 05, 2008 16:00:00 - 18:00:00 2:00:00 first line
514
+ and a second line
428
515
  2:00:00
429
- ---------------------------------------------------------------------
516
+ --------------------------------------------------------------------------------
430
517
  Total 2:00:00
431
- -------------------------------------------------------------------------
432
- Grand Total 10:00:00
433
518
  OUTPUT
434
519
  end
435
520
 
@@ -484,10 +569,23 @@ Grand Total 10:00:00
484
569
  end
485
570
 
486
571
 
487
- it "should display all timesheets" do
488
- Timetrap::Timer.current_sheet = 'another'
489
- invoke 'display all'
490
- $stdout.string.should == @desired_output_for_all
572
+ it "should display long notes nicely" do
573
+ Timetrap::Timer.current_sheet = 'LongNoteSheet'
574
+ invoke 'display'
575
+ $stdout.string.should == @desired_output_for_long_note_sheet
576
+ end
577
+
578
+ it "should display long notes with linebreaks nicely" do
579
+ Timetrap::Timer.current_sheet = 'SheetWithLineBreakNote'
580
+ invoke 'display'
581
+ $stdout.string.should == @desired_output_for_note_with_linebreak
582
+ end
583
+
584
+ it "should display long notes with ids nicely" do
585
+ Timetrap::DB["UPDATE entries SET id = 60000 WHERE id = 6"].all
586
+ Timetrap::Timer.current_sheet = 'LongNoteSheet'
587
+ invoke 'display --ids'
588
+ $stdout.string.should == @desired_output_for_long_note_sheet_with_ids
491
589
  end
492
590
 
493
591
  it "should not display archived for all timesheets" do
@@ -617,17 +715,17 @@ start,end,note,sheet
617
715
  invoke 'in'
618
716
  invoke 'display --format ical'
619
717
 
620
- $stdout.string.scan(/BEGIN:VEVENT/).should have(2).item
718
+ expect($stdout.string.scan(/BEGIN:VEVENT/).size).to eq(2)
621
719
  end
622
720
 
623
721
  it "should filter events by the passed dates" do
624
722
  invoke 'display --format ical --start 2008-10-03 --end 2008-10-03'
625
- $stdout.string.scan(/BEGIN:VEVENT/).should have(1).item
723
+ expect($stdout.string.scan(/BEGIN:VEVENT/).size).to eq(1)
626
724
  end
627
725
 
628
726
  it "should not filter events by date when none are passed" do
629
727
  invoke 'display --format ical'
630
- $stdout.string.scan(/BEGIN:VEVENT/).should have(2).item
728
+ expect($stdout.string.scan(/BEGIN:VEVENT/).size).to eq(2)
631
729
  end
632
730
 
633
731
  it "should export a sheet to an ical format" do
@@ -701,28 +799,56 @@ END:VCALENDAR
701
799
  end
702
800
 
703
801
  describe "with require_note config option set" do
704
- before do
705
- with_stubbed_config 'require_note' => true
706
- end
802
+ context "without a note_editor" do
803
+ before do
804
+ with_stubbed_config 'require_note' => true, 'note_editor' => false
805
+ end
707
806
 
708
- it "should prompt for a note if one isn't passed" do
709
- $stdin.string = "an interactive note\n"
710
- invoke "in"
711
- $stderr.string.should include('enter a note')
712
- Timetrap::Timer.active_entry.note.should == "an interactive note"
713
- end
807
+ it "should prompt for a note if one isn't passed" do
808
+ $stdin.string = "an interactive note\n"
809
+ invoke "in"
810
+ $stderr.string.should include('enter a note')
811
+ Timetrap::Timer.active_entry.note.should == "an interactive note"
812
+ end
714
813
 
715
- it "should not prompt for a note if one is passed" do
716
- $stdin.string = "an interactive note\n"
717
- invoke "in a normal note"
718
- Timetrap::Timer.active_entry.note.should == "a normal note"
814
+ it "should not prompt for a note if one is passed" do
815
+ $stdin.string = "an interactive note\n"
816
+ invoke "in a normal note"
817
+ Timetrap::Timer.active_entry.note.should == "a normal note"
818
+ end
819
+
820
+ it "should not stop the running entry or prompt" do
821
+ invoke "in a normal note"
822
+ $stdin.string = "an interactive note\n"
823
+ invoke "in"
824
+ Timetrap::Timer.active_entry.note.should == "a normal note"
825
+ end
719
826
  end
720
827
 
721
- it "should not stop the running entry or prompt" do
722
- invoke "in a normal note"
723
- $stdin.string = "an interactive note\n"
724
- invoke "in"
725
- Timetrap::Timer.active_entry.note.should == "a normal note"
828
+ context "with a note editor" do
829
+ let(:note_editor_command) { 'vim' }
830
+ before do
831
+ with_stubbed_config 'require_note' => true, 'note_editor' => note_editor_command
832
+ end
833
+
834
+ it "should open an editor for writing the note" do |example|
835
+ Timetrap::CLI.stub(:system) do |editor_command|
836
+ path = editor_command.match(/#{note_editor_command} (?<path>.*)/)
837
+ File.write(path[:path], "written in editor")
838
+ end
839
+ invoke "in"
840
+ $stderr.string.should_not include('enter a note')
841
+ Timetrap::Timer.active_entry.note.should == "written in editor"
842
+ end
843
+
844
+ it "should preserve linebreaks from editor" do |example|
845
+ Timetrap::CLI.stub(:system) do |editor_command|
846
+ path = editor_command.match(/#{note_editor_command} (?<path>.*)/)
847
+ File.write(path[:path], "line1\nline2")
848
+ end
849
+ invoke "in"
850
+ Timetrap::Timer.active_entry.note.should == "line1\nline2"
851
+ end
726
852
  end
727
853
  end
728
854
 
@@ -868,10 +994,10 @@ END:VCALENDAR
868
994
  describe "kill" do
869
995
  it "should give me a chance not to fuck up" do
870
996
  entry = create_entry
871
- lambda do
997
+ expect do
872
998
  $stdin.string = ""
873
999
  invoke "kill #{entry.sheet}"
874
- end.should_not change(Timetrap::Entry, :count).by(-1)
1000
+ end.not_to change(Timetrap::Entry, :count)
875
1001
  end
876
1002
 
877
1003
  it "should delete a timesheet" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timetrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.0
4
+ version: 1.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Goldstein
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-08 00:00:00.000000000 Z
11
+ date: 2016-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler