medo 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/Gemfile +12 -0
  2. data/Gemfile.lock +48 -0
  3. data/LICENSE.txt +20 -0
  4. data/README.md +14 -0
  5. data/Rakefile +29 -0
  6. data/VERSION +1 -0
  7. data/bin/medo +59 -0
  8. data/features/add_notes.feature +18 -0
  9. data/features/add_task.feature +12 -0
  10. data/features/list_tasks.feature +25 -0
  11. data/features/step_definitions/add_task_steps.rb +3 -0
  12. data/features/step_definitions/list_tasks_steps.rb +6 -0
  13. data/features/support/env.rb +14 -0
  14. data/lib/medo.rb +6 -0
  15. data/lib/medo/commands/clear.rb +9 -0
  16. data/lib/medo/commands/delete.rb +13 -0
  17. data/lib/medo/commands/done.rb +13 -0
  18. data/lib/medo/commands/list.rb +16 -0
  19. data/lib/medo/commands/new.rb +15 -0
  20. data/lib/medo/commands/note.rb +18 -0
  21. data/lib/medo/commands/show.rb +19 -0
  22. data/lib/medo/file_task_storage.rb +53 -0
  23. data/lib/medo/json_task_reader.rb +31 -0
  24. data/lib/medo/json_task_writer.rb +33 -0
  25. data/lib/medo/support.rb +6 -0
  26. data/lib/medo/support/decorator.rb +40 -0
  27. data/lib/medo/task.rb +63 -0
  28. data/lib/medo/task_reader.rb +8 -0
  29. data/lib/medo/task_writer.rb +21 -0
  30. data/lib/medo/terminal.rb +6 -0
  31. data/lib/medo/text_task_writer.rb +137 -0
  32. data/lib/medo/text_task_writer/decorators/colors_decorator.rb +28 -0
  33. data/lib/medo/text_task_writer/decorators/numbers_decorator.rb +37 -0
  34. data/spec/lib/file_task_storage_spec.rb +59 -0
  35. data/spec/lib/json_task_reader_spec.rb +26 -0
  36. data/spec/lib/json_task_writer_spec.rb +32 -0
  37. data/spec/lib/task_reader_spec.rb +9 -0
  38. data/spec/lib/task_spec.rb +101 -0
  39. data/spec/lib/task_writer_spec.rb +18 -0
  40. data/spec/lib/text_task_writer_spec.rb +106 -0
  41. data/spec/spec_helper.rb +24 -0
  42. data/spec/support/task_stubs_spec_helper.rb +41 -0
  43. metadata +189 -0
@@ -0,0 +1,26 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ require 'support/task_stubs_spec_helper'
3
+ require 'medo/json_task_reader'
4
+ require 'stringio'
5
+
6
+ include Medo
7
+
8
+ describe JsonTaskReader do
9
+ unless defined? Task
10
+ class Task; end
11
+ end
12
+
13
+ include TaskStubsSpecHelper
14
+
15
+ it "should read tasks" do
16
+ fake_input = StringIO.new '[{"done":false,"description":"Buy Milk","created_at":"2012-01-05 12:04:00",'\
17
+ '"completed_at":null,"notes":[]},{"done":true,"description":"Buy Butter","created_at":"2012-01-05 15:30:00",'\
18
+ '"completed_at":"2012-01-05 16:30:00","notes":["Note 1","Note 2"]}]'
19
+
20
+ Task.should_receive(:from_attributes).with(pending_task_attributes).and_return(1)
21
+ Task.should_receive(:from_attributes).with(completed_task_attributes).and_return(2)
22
+
23
+ JsonTaskReader.new(fake_input).read.should == [1, 2]
24
+ end
25
+ end
26
+
@@ -0,0 +1,32 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ require 'support/task_stubs_spec_helper'
3
+ require 'medo/json_task_writer'
4
+
5
+ include Medo
6
+
7
+ describe JsonTaskWriter do
8
+ include TaskStubsSpecHelper
9
+
10
+ describe "#write" do
11
+ let(:task_writer) { task_writer = JsonTaskWriter.new(fake_output) }
12
+
13
+ it "should print tasks as json" do
14
+ task_writer.add_task(pending_task)
15
+ task_writer.add_task(completed_task)
16
+ task_writer.write
17
+
18
+ JSON.parse(fake_output.string).should == [
19
+ convert_time(pending_task_attributes),
20
+ convert_time(completed_task_attributes)
21
+ ]
22
+ end
23
+
24
+ def convert_time(hash)
25
+ hash.merge!(
26
+ "created_at" => hash["created_at"].to_s,
27
+ "completed_at" => (hash["completed_at"].to_s if hash["completed_at"])
28
+ )
29
+ end
30
+ end
31
+ end
32
+
@@ -0,0 +1,9 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ require 'medo/task_reader'
3
+
4
+ describe TaskReader do
5
+ specify "#read should be abstract" do
6
+ expect { TaskReader.new.read }.to raise_error NotImplementedError
7
+ end
8
+ end
9
+
@@ -0,0 +1,101 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ require 'medo/task'
3
+
4
+ describe Medo::Task do
5
+ it "should have description attribute" do
6
+ Medo::Task.new("description").description.should == "description"
7
+ end
8
+
9
+ it "should require description to be set" do
10
+ proc { Medo::Task.new("") }.should raise_error(ArgumentError)
11
+ proc { Medo::Task.new(" ") }.should raise_error(ArgumentError)
12
+ end
13
+
14
+ it "should allow notes to be set upon creation" do
15
+ Medo::Task.new("description", :notes => ["1", "2"]).notes.should == ["1", "2"]
16
+ Medo::Task.new("description", :notes => 0).notes.should == ["0"]
17
+ Medo::Task.new("description", :notes => [0, nil]).notes.should == ["0"]
18
+ end
19
+
20
+ it "should assign creation time upon instantiation" do
21
+ fake_clock = stub(:now => Time.now)
22
+ using_fake_clock(fake_clock) do
23
+ Medo::Task.new("description").created_at.should == fake_clock.now
24
+ end
25
+ end
26
+
27
+ it "should allow assigning notes to the task" do
28
+ task = Medo::Task.new("description")
29
+ task.notes << "My Note"
30
+ task.notes.should include("My Note")
31
+ end
32
+
33
+ it "should not allow comparison with shit" do
34
+ task1 = Medo::Task.new("asdfsd")
35
+ proc { task1 <=> :foo }.should raise_error(ArgumentError)
36
+ end
37
+
38
+ it "should be comparable by creation date and completion date" do
39
+ clock = Object.new
40
+
41
+ def clock.now
42
+ @tick ||= 0
43
+ @tick += 1
44
+ end
45
+
46
+ using_fake_clock(clock) do
47
+ task1 = Medo::Task.new("description of task 1")
48
+ task2 = Medo::Task.new("description of task 2")
49
+ task3 = Medo::Task.new("description of task 3")
50
+ task4 = Medo::Task.new("description of task 4")
51
+
52
+ [task1, task3, task4, task2].sort.should == [task4, task3, task2, task1]
53
+
54
+ task3.done
55
+ task2.done
56
+
57
+ [task1, task3, task4, task2].sort.should == [task4, task1, task2, task3]
58
+ end
59
+ end
60
+
61
+ it "should not be done by default" do
62
+ Medo::Task.new("Buy milk").should_not be_done
63
+ end
64
+
65
+ it "should be done after marked as such" do
66
+ task = Medo::Task.new("Buy milk")
67
+ task.done
68
+ task.should be_done
69
+ end
70
+
71
+ describe ".from_attributes" do
72
+ it "should allow all attributes to be set from hash" do
73
+ created_at = Time.now
74
+ completed_at = Time.now
75
+ task = Medo::Task.from_attributes("description" => "d",
76
+ "notes" => ["n"],
77
+ "done" => true,
78
+ "completed_at" => completed_at,
79
+ "created_at" => created_at)
80
+ task.description.should == "d"
81
+ task.notes.should == ["n"]
82
+ task.completed_at.should == completed_at
83
+ task.created_at.should == created_at
84
+ task.should be_done
85
+ end
86
+
87
+ it "should require description, created_at, and completed at if done set to true" do
88
+ proc { Medo::Task.from_attributes({}) }.should raise_error(ArgumentError, "No description given!")
89
+ proc { Medo::Task.from_attributes("description" => " ") }.should raise_error(ArgumentError, "No description given!")
90
+ proc { Medo::Task.from_attributes("description" => "asdf") }.should raise_error(ArgumentError, "Missing created_at")
91
+ proc { Medo::Task.from_attributes("description" => "a", "created_at" => Time.now, "done" => true) }.should raise_error(ArgumentError, "Missing completed_at")
92
+ end
93
+ end
94
+
95
+ def using_fake_clock(fake_clock)
96
+ Medo::Task.clock = fake_clock
97
+ yield
98
+ Medo::Task.clock = Time
99
+ end
100
+ end
101
+
@@ -0,0 +1,18 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ require 'medo/task_writer'
3
+
4
+ describe TaskWriter do
5
+ describe "#add_task" do
6
+ it "should accept task to be printed" do
7
+ task = stub
8
+ writer = TaskWriter.new
9
+ writer.add_task(task)
10
+ writer.tasks_to_write.should == [task]
11
+ end
12
+ end
13
+
14
+ specify "#write should be abstract" do
15
+ expect { TaskWriter.new.write }.to raise_error NotImplementedError
16
+ end
17
+ end
18
+
@@ -0,0 +1,106 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ require 'support/task_stubs_spec_helper'
3
+ require 'medo/text_task_writer'
4
+
5
+ describe TextTaskWriter do
6
+ include TaskStubsSpecHelper
7
+
8
+ describe "#write" do
9
+ let(:task_writer) { task_writer = TextTaskWriter.new(fake_output) }
10
+
11
+ it "should pretty print the task to STDOUT" do
12
+ task_writer.add_task(pending_task)
13
+ task_writer.write
14
+
15
+ fake_output.string.should == <<-TXT
16
+ [ ] Buy Milk (12:04)
17
+ TXT
18
+ end
19
+
20
+ it "should pretty print completed tasks" do
21
+ task_writer.add_task(completed_task)
22
+ task_writer.write
23
+
24
+ fake_output.string.should == <<-TXT
25
+ [+] Buy Butter [16:30]
26
+
27
+ Note 1
28
+ Note 2
29
+
30
+ TXT
31
+ end
32
+
33
+ it "should split incomplete and complete tasks" do
34
+ task_writer.add_task(pending_task)
35
+ task_writer.add_task(completed_task)
36
+ task_writer.write
37
+
38
+ fake_output.string.should == <<-TXT
39
+ [ ] Buy Milk (12:04)
40
+ ----------------------
41
+ [+] Buy Butter [16:30]
42
+
43
+ Note 1
44
+ Note 2
45
+
46
+ TXT
47
+ end
48
+
49
+ it "should wrap task desriptions to fit terminal width" do
50
+ Terminal.stub(:instance => stub(:size => [20, 40])) #cols, lines
51
+
52
+ task_writer.add_task(pending_task)
53
+ task_writer.add_task(completed_task)
54
+ task_writer.write
55
+
56
+ fake_output.string.should == <<-TXT
57
+ [ ] Buy Milk (12:04)
58
+ --------------------
59
+ [+] Buy
60
+ Butter [16:30]
61
+
62
+ Note 1
63
+ Note 2
64
+
65
+ TXT
66
+ end
67
+
68
+ it "should wrap notes to fit terminal width" do
69
+ Terminal.stub(:instance => stub(:size => [20, 40])) #cols, lines
70
+
71
+ task_writer.add_task(pending_task)
72
+ pending_task.stub(:notes => ["Note 1 is too long to fit the terminal"])
73
+ task_writer.write
74
+
75
+ fake_output.string.should == <<-TXT
76
+ [ ] Buy Milk (12:04)
77
+
78
+ Note 1 is too
79
+ long to fit
80
+ the terminal
81
+
82
+ TXT
83
+ end
84
+
85
+ it "should wrap very longs words nicely" do
86
+ Terminal.stub(:instance => stub(:size => [20, 40])) #cols, lines
87
+
88
+ pending_task.stub(:notes => ["this is a very long sentence containing the Honorificabilitudinitatibus word"])
89
+
90
+ task_writer.add_task(pending_task)
91
+ task_writer.write
92
+
93
+ fake_output.string.should == <<-TXT
94
+ [ ] Buy Milk (12:04)
95
+
96
+ this is a very
97
+ long sentence
98
+ containing the
99
+ Honorificabili
100
+ tudinitatibus
101
+ word
102
+
103
+ TXT
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ if ENV['COVERAGE']
5
+ require 'simplecov'
6
+ SimpleCov.start do
7
+ add_filter '/spec/'
8
+
9
+ add_filter do |f|
10
+ f.lines.count < 5
11
+ end
12
+ end
13
+ end
14
+
15
+ require 'rspec'
16
+ require 'rspec/autorun'
17
+
18
+ $:.unshift File.expand_path(File.dirname(__FILE__))
19
+ $:.unshift File.expand_path('../lib', File.dirname(__FILE__))
20
+
21
+ require 'medo'
22
+ require 'medo/support'
23
+
24
+ include Medo
@@ -0,0 +1,41 @@
1
+ require 'stringio'
2
+ require 'time'
3
+
4
+ module TaskStubsSpecHelper
5
+ def self.included(base)
6
+ base.class_eval do
7
+ let(:pending_task_attributes) do
8
+ {
9
+ "description" => "Buy Milk",
10
+ "created_at" => Time.parse("2012-01-05 12:04:00"),
11
+ "completed_at" => nil,
12
+ "done" => false,
13
+ "notes" => []
14
+ }
15
+ end
16
+
17
+ let(:completed_task_attributes) do
18
+ {
19
+ "description" => "Buy Butter",
20
+ "created_at" => Time.parse("2012-01-05 15:30:00"),
21
+ "completed_at" => Time.parse("2012-01-05 16:30:00"),
22
+ "done" => true,
23
+ "notes" => ["Note 1", "Note 2"]
24
+ }
25
+ end
26
+
27
+ let(:pending_task) do
28
+ attrs = pending_task_attributes
29
+ stub(:Task, attrs.merge("done?" => attrs["done"]))
30
+ end
31
+
32
+ let(:completed_task) do
33
+ attrs = completed_task_attributes
34
+ stub(:Task, attrs.merge("done?" => attrs["done"]))
35
+ end
36
+
37
+ let(:fake_output) { fake_output = StringIO.new }
38
+ end
39
+ end
40
+ end
41
+
metadata ADDED
@@ -0,0 +1,189 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: medo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Vladimir Yarotsky
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: gli
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 2.0.0.rc4
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 2.0.0.rc4
30
+ - !ruby/object:Gem::Dependency
31
+ name: rainbow
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.1'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.1'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '2.10'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.10'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '0.9'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '0.9'
78
+ - !ruby/object:Gem::Dependency
79
+ name: aruba
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '0.4'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '0.4'
94
+ - !ruby/object:Gem::Dependency
95
+ name: simplecov
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '0.6'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '0.6'
110
+ description: ! 'The ''medo'' application allows you to keep track of your
111
+
112
+ tasks (basically a to-do app) through command line interface
113
+
114
+ '
115
+ email: vladimir.yarotksy@gmail.com
116
+ executables:
117
+ - medo
118
+ extensions: []
119
+ extra_rdoc_files: []
120
+ files:
121
+ - bin/medo
122
+ - lib/medo/commands/clear.rb
123
+ - lib/medo/commands/delete.rb
124
+ - lib/medo/commands/done.rb
125
+ - lib/medo/commands/list.rb
126
+ - lib/medo/commands/new.rb
127
+ - lib/medo/commands/note.rb
128
+ - lib/medo/commands/show.rb
129
+ - lib/medo/file_task_storage.rb
130
+ - lib/medo/json_task_reader.rb
131
+ - lib/medo/json_task_writer.rb
132
+ - lib/medo/support/decorator.rb
133
+ - lib/medo/support.rb
134
+ - lib/medo/task.rb
135
+ - lib/medo/task_reader.rb
136
+ - lib/medo/task_writer.rb
137
+ - lib/medo/terminal.rb
138
+ - lib/medo/text_task_writer/decorators/colors_decorator.rb
139
+ - lib/medo/text_task_writer/decorators/numbers_decorator.rb
140
+ - lib/medo/text_task_writer.rb
141
+ - lib/medo.rb
142
+ - spec/lib/file_task_storage_spec.rb
143
+ - spec/lib/json_task_reader_spec.rb
144
+ - spec/lib/json_task_writer_spec.rb
145
+ - spec/lib/task_reader_spec.rb
146
+ - spec/lib/task_spec.rb
147
+ - spec/lib/task_writer_spec.rb
148
+ - spec/lib/text_task_writer_spec.rb
149
+ - spec/spec_helper.rb
150
+ - spec/support/task_stubs_spec_helper.rb
151
+ - features/add_notes.feature
152
+ - features/add_task.feature
153
+ - features/list_tasks.feature
154
+ - features/step_definitions/add_task_steps.rb
155
+ - features/step_definitions/list_tasks_steps.rb
156
+ - features/support/env.rb
157
+ - Gemfile
158
+ - Gemfile.lock
159
+ - Rakefile
160
+ - LICENSE.txt
161
+ - README.md
162
+ - VERSION
163
+ homepage: http://github.com/v-yarotsky/medo
164
+ licenses:
165
+ - MIT
166
+ post_install_message:
167
+ rdoc_options: []
168
+ require_paths:
169
+ - lib
170
+ required_ruby_version: !ruby/object:Gem::Requirement
171
+ none: false
172
+ requirements:
173
+ - - ! '>='
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ required_rubygems_version: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>='
180
+ - !ruby/object:Gem::Version
181
+ version: 1.3.6
182
+ requirements: []
183
+ rubyforge_project:
184
+ rubygems_version: 1.8.21
185
+ signing_key:
186
+ specification_version: 3
187
+ summary: Simple CLI todo manager app
188
+ test_files: []
189
+ has_rdoc: