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 +4 -4
- data/.travis.yml +1 -0
- data/CONTRIBUTORS +1 -0
- data/README.md +18 -2
- data/lib/timetrap.rb +1 -0
- data/lib/timetrap/cli.rb +41 -9
- data/lib/timetrap/config.rb +3 -1
- data/lib/timetrap/formatters/text.rb +50 -8
- data/lib/timetrap/version.rb +1 -1
- data/spec/timetrap_spec.rb +172 -46
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 271617ba22c6a444786172a06c319c130e520e3e
|
4
|
+
data.tar.gz: 58a80a95272541cf095d4727e580a1feda1b49f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75ac29be79462ac44122fedbe8255b48091d749cd08eed5ef672327c7d1a8e949f40ffdb584d3a203e2a3a42ea4ff0ef2ba81ca13c25477555e5d0d96556d409
|
7
|
+
data.tar.gz: d85f15fd101a3a3a321b2d6283c744ac1f7fdc919ee292a8366ad71543841fb70253c2274b8bbd691fae9ef6ac260386e51adf23c1b22fd344b6e287ed989dfb
|
data/.travis.yml
CHANGED
data/CONTRIBUTORS
CHANGED
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
|
|
data/lib/timetrap.rb
CHANGED
data/lib/timetrap/cli.rb
CHANGED
@@ -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>
|
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
|
-
|
243
|
-
if unused_args =~ /.+/
|
244
|
-
note = unused_args
|
245
|
+
if Config['note_editor']
|
245
246
|
if args['-z']
|
246
|
-
note = [entry.note,
|
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
|
-
|
267
|
-
|
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
|
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
|
data/lib/timetrap/config.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/timetrap/version.rb
CHANGED
data/spec/timetrap_spec.rb
CHANGED
@@ -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(:[])
|
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
|
144
|
+
File.exist?(config_file).should be_falsey
|
133
145
|
invoke "configure"
|
134
|
-
File.exist?(config_file).should
|
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
|
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
|
-
@
|
414
|
-
Timesheet:
|
482
|
+
@desired_output_for_long_note_sheet = <<-OUTPUT
|
483
|
+
Timesheet: LongNoteSheet
|
415
484
|
Day Start End Duration Notes
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
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
|
-
|
510
|
+
@desired_output_for_note_with_linebreak = <<-OUTPUT
|
511
|
+
Timesheet: SheetWithLineBreakNote
|
426
512
|
Day Start End Duration Notes
|
427
|
-
Sun Oct 05, 2008
|
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
|
488
|
-
Timetrap::Timer.current_sheet = '
|
489
|
-
invoke 'display
|
490
|
-
$stdout.string.should == @
|
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/).
|
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/).
|
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/).
|
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
|
-
|
705
|
-
|
706
|
-
|
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
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
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
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
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
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
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
|
-
|
997
|
+
expect do
|
872
998
|
$stdin.string = ""
|
873
999
|
invoke "kill #{entry.sheet}"
|
874
|
-
end.
|
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.
|
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-
|
11
|
+
date: 2016-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|