timetrap 1.10.0 → 1.11.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.
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