idid 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.8.7"
4
+ - "1.9.2"
5
+ - "1.9.3"
6
+ - jruby-18mode # JRuby in 1.8 mode
7
+ - jruby-19mode # JRuby in 1.9 mode
8
+ - rbx-18mode
9
+ - rbx-19mode
data/README.md CHANGED
@@ -1,11 +1,15 @@
1
1
  # Idid
2
2
 
3
+ [![Build Status](https://travis-ci.org/foxycoder/idid.png)](https://travis-ci.org/foxycoder/idid)
4
+
3
5
  Ruby CLI to [iDoneThis](http://idonethis.com).
4
6
 
5
7
  ## Usage (easy)
6
8
 
7
9
  $ idid Something awesome that my colleagues should know about.
8
10
 
11
+ See `idid -h` for more available options.
12
+
9
13
  ## Installation
10
14
 
11
15
  $ [sudo] gem install idid
@@ -13,9 +17,8 @@ Ruby CLI to [iDoneThis](http://idonethis.com).
13
17
  ## Todo
14
18
 
15
19
  1. Write some more tests for mail delivery configurations.
16
- 2. Keeping of dones locally for easy review.
17
- 3. Off-line support (queue dones and send later).
18
- 4. Support for iDoneThis personal.
20
+ 2. Off-line support (queue dones and send later).
21
+ 3. Support for iDoneThis personal.
19
22
 
20
23
  ## Contributing
21
24
 
data/Rakefile CHANGED
@@ -1 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ desc 'Run all the tests'
4
+ task :default do
5
+ exit system('bundle exec rspec spec --color')
6
+ end
data/bin/idid CHANGED
@@ -1,17 +1,42 @@
1
1
  #!/usr/bin/env ruby
2
-
2
+ require 'optparse'
3
3
  require File.expand_path('../../lib/idid', __FILE__)
4
4
 
5
+ options = {}
6
+
7
+ OptionParser.new do |opts|
8
+ # Show help screen
9
+ opts.on( '-h', '--help', 'Display this screen' ) do
10
+ puts opts
11
+ exit
12
+ end
5
13
 
14
+ # Show list of done items
15
+ list_desc = "Show done log for date. Default: today."
16
+ options[:list] = nil
17
+ opts.on('-l', '--list [YYYY-MM-DD]', list_desc) do |f|
18
+ options[:list] = f || Time.now.strftime('%Y-%m-%d')
19
+ end
20
+ end.parse!
6
21
 
7
- begin
8
- config = Idid::Configuration.new
9
- rescue
10
- config = Idid::Interactive.create_config
11
- config.write
12
- end
22
+ if options[:list]
23
+ puts Idid::Task.list options[:list]
24
+ else
25
+ begin
26
+ config = Idid::Configuration.new
27
+ rescue
28
+ config = Idid::Interactive.create_config
29
+ config.write
30
+ Idid::Interactive.status "Got your settings. Let's record your progress!"
31
+ end
13
32
 
14
- Idid.configuration = config
15
- Idid.send ARGV
33
+ if ARGV.any?
34
+ task = Idid::Task.new ARGV.join " "
35
+ task.save
16
36
 
17
- puts 'done'
37
+ Idid::Delivery.new(config).email task.to_s
38
+ Idid::Interactive.status "Got it! Let's get some more done!"
39
+ else
40
+ Idid::Interactive.fail "Shoot! An empty message cannot be send!"
41
+ end
42
+ end
data/idid.gemspec CHANGED
@@ -17,7 +17,10 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
19
 
20
+ gem.add_development_dependency 'rake'
20
21
  gem.add_development_dependency 'rspec', '~> 2.12.0'
22
+ gem.add_development_dependency 'travis-lint'
21
23
 
22
24
  gem.add_runtime_dependency 'mail', '~> 2.5.3'
25
+ gem.add_runtime_dependency 'json', '~> 1.7.5'
23
26
  end
@@ -1,7 +1,7 @@
1
1
  module Idid
2
2
  class Configuration
3
3
 
4
- SMTP_DEFAULTS = {
4
+ SMTP_DEFAULTS = {
5
5
  :address => 'smtp.gmail.com',
6
6
  :port => '587',
7
7
  :user_name => ENV['GMAIL_SMTP_USER'],
@@ -22,26 +22,26 @@ module Idid
22
22
  attr_accessor :delivery
23
23
 
24
24
  # Public: configuration to use with iDoneThis
25
- #
25
+ #
26
26
  # options - Hash with configuration options
27
27
  # project - Name of the project to post to (e.g.
28
28
  # project.idonethis.com)
29
29
  # email - Email address to use when sending mail.
30
- # delivery - Email delivery configuration Hash:
30
+ # delivery - Email delivery configuration Hash:
31
31
  # method - Symbol (:smtp|:sendmail|:exim)
32
32
  # options - Configuration Hash for the
33
33
  # delivery method (see:
34
34
  # https://github.com/mikel/mail).
35
35
  #
36
36
  # Returns a new Idid::Configuration instance
37
- def initialize options = {}
38
- options = options.merge(read_config) if read_config
39
- raise ArgumentError.new("Provide a project to use.") unless options['project']
40
- raise ArgumentError.new("Provide an email address.") unless options['email']
41
- raise ArgumentError.new("Provide a delivery method.") unless options['delivery']
37
+ def initialize(options = {})
38
+ options = read_config.merge options if read_config
39
+ raise ArgumentError.new "Provide a project to use." unless options['project']
40
+ raise ArgumentError.new "Provide an email address." unless options['email']
41
+ raise ArgumentError.new "Provide a delivery method." unless options['delivery']
42
42
 
43
- @project = options['project']
44
- @email = options['email']
43
+ @project = options['project']
44
+ @email = options['email']
45
45
  @delivery = options['delivery']
46
46
  end
47
47
 
@@ -68,7 +68,7 @@ module Idid
68
68
  end
69
69
 
70
70
  def self.config_file
71
- File.join( ENV['HOME'], '.idid.yml' )
71
+ File.join ENV['HOME'], '.idid.yml'
72
72
  end
73
73
  end
74
74
  end
@@ -0,0 +1,60 @@
1
+ module Idid
2
+ class Delivery
3
+
4
+ attr_accessor :config
5
+
6
+ # Public: Initialize a new Delivery. It will automatically set the correct
7
+ # delivery options
8
+ #
9
+ # config - The Hash options to use when sending the email to iDoneThis
10
+ #
11
+ # Returns a new instance of Delivery
12
+ def initialize(config)
13
+ @config = config
14
+ setup_delivery
15
+ end
16
+
17
+ # Public: Send email to iDoneThis for logging
18
+ #
19
+ # message - The String with the actual activity you want to log
20
+ #
21
+ # Returns Mail::Message object
22
+ def email(message)
23
+ config = @config # Needed because @config is not in the block scope below
24
+
25
+ Mail.deliver do
26
+ from config.email
27
+ to "#{config.project}@team.idonethis.com"
28
+ subject "I did this"
29
+ body message
30
+ end
31
+ end
32
+
33
+ private
34
+ # Private: Set the right delivery options for Mail to use, based on the
35
+ # settings in the configuration file. Defaults to sending mail via SMTP, if
36
+ # no or unknown delivery method is specified.
37
+ #
38
+ # Returns nothing
39
+ def setup_delivery
40
+ method = @config.delivery['method'] || :smtp
41
+ options = @config.delivery['options'] || {}
42
+
43
+ options.keys.each do |key|
44
+ options[(key.to_sym rescue key) || key] = options.delete(key)
45
+ end
46
+
47
+ options = Idid::Configuration::SMTP_DEFAULTS.merge options if method == :smtp
48
+ options = Idid::Configuration::EXIM_DEFAULTS.merge options if method == :exim
49
+
50
+ mail_defaults_for method, options
51
+ end
52
+
53
+ def mail_defaults_for(method, options = {})
54
+ Mail.defaults do
55
+ delivery_method method, options
56
+ end
57
+ end
58
+
59
+ end
60
+ end
@@ -6,8 +6,7 @@ module Idid
6
6
  status "Please take a moment to create a new configuration.."
7
7
  config = user_config
8
8
  config['delivery'] ||= {}
9
- user_config_from_key 'project',
10
- "What is the name of your iDoneThis project (look at the url: <project>.idonethis.com)", nil, config
9
+ user_config_from_key 'project', "What is the name of your iDoneThis project (look at the url: <project>.idonethis.com)", nil, config
11
10
  user_config_from_key 'email', "What is your associated email address for this iDoneThis project?", nil, config
12
11
  user_config_from_key 'method', "How do you want to send emails to iDoneThis? (smtp, sendmail, exim)", 'smtp', config['delivery']
13
12
 
@@ -25,7 +24,7 @@ module Idid
25
24
  user_config_from_key key, key.to_s, default, config['delivery']['options']
26
25
  end
27
26
 
28
- Idid::Configuration.new(config)
27
+ Idid::Configuration.new config
29
28
  end
30
29
 
31
30
  def user_config_from_key(key, text, default, config = nil)
@@ -46,7 +45,7 @@ module Idid
46
45
  puts "\e[36m#{text}\e[0m"
47
46
  end
48
47
 
49
- def fail(text='Failed!')
48
+ def fail(text = 'Failed!')
50
49
  puts "\e[31m#{text}\e[0m"
51
50
  end
52
51
 
data/lib/idid/task.rb ADDED
@@ -0,0 +1,90 @@
1
+ require 'date'
2
+ require 'json'
3
+
4
+ module Idid
5
+ class Task
6
+ attr_accessor :contents, :log, :logdate
7
+
8
+ # Public: Initialize a new Task
9
+ #
10
+ # contents - The String containing the task that has been done
11
+ #
12
+ # Returns an instance of Task
13
+ def initialize(contents, logdate = nil)
14
+ @contents = contents
15
+ @log = Task.read_log
16
+ @logdate = logdate || Date.today
17
+ end
18
+
19
+ # Public: Save a task to the log file. If there were tasks for this day
20
+ # already, it's appended to that days log. Otherwise, a new day is added to
21
+ # the log.
22
+ #
23
+ # Returns boolean
24
+ def save
25
+ logdate = @logdate.strftime '%Y-%m-%d'
26
+
27
+ if @log.has_key? logdate
28
+ @log[logdate].push @contents
29
+ else
30
+ @log[logdate] = [@contents]
31
+ end
32
+
33
+ Task.write_log @log
34
+ end
35
+
36
+ # Public: Transform Task into a String
37
+ #
38
+ # Returns the String with the contents of the task
39
+ def to_s
40
+ @contents
41
+ end
42
+
43
+ # Public: Lists all activities for a given date.
44
+ #
45
+ # date - The String date you wish to show the entries of, in the format
46
+ # YYYY-MM-DD
47
+ #
48
+ # Returns the String showing the logged activities
49
+ def self.list(date)
50
+ formatted_date = Date.parse(date).strftime '%e %B %Y'
51
+ list = read_log[date]
52
+
53
+ if list.nil?
54
+ "Could not find any activity for#{formatted_date}"
55
+ else
56
+ formatted_log = list.map{|l| '* ' + l }.join "\n"
57
+ "Log for#{formatted_date}:\n#{formatted_log}"
58
+ end
59
+ end
60
+
61
+ private
62
+ # Private: Location of the log file (~/.idid)
63
+ #
64
+ # Returns the String with the location of the log file
65
+ def self.logfile
66
+ logfile = File.join ENV['HOME'], '.idid'
67
+ end
68
+
69
+ # Private: Reads the log file into memory.
70
+ #
71
+ # Returns the Hash containing all log entries, or an empty hash if no
72
+ # entries were found
73
+ def self.read_log
74
+ if File.exists? logfile
75
+ JSON.load open(logfile) rescue {}
76
+ else
77
+ {}
78
+ end
79
+ end
80
+
81
+ # Private: Writes the log file to disk in JSON format
82
+ #
83
+ # log - The Hash containing the done log
84
+ #
85
+ # Returns boolean
86
+ def self.write_log(log)
87
+ File.open(logfile, 'w') { |f| f.write log.to_json }
88
+ end
89
+ end
90
+ end
data/lib/idid/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Idid
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/lib/idid.rb CHANGED
@@ -4,53 +4,4 @@ require 'yaml'
4
4
  Dir[File.expand_path("../idid/**/*.rb", __FILE__)].each {|f| require f}
5
5
 
6
6
  module Idid
7
- class << self
8
- attr_accessor :configuration
9
-
10
- def send *words
11
- setup_delivery
12
- Mail.deliver do
13
- from Idid.configuration.email
14
- to "#{Idid.configuration.project}@team.idonethis.com"
15
- subject "I did this"
16
- body words.flatten.join(" ")
17
- end
18
- end
19
-
20
- def setup_delivery
21
- method = Idid.configuration.delivery['method']
22
- options = Idid.configuration.delivery['options'] || {}
23
-
24
- options.keys.each do |key|
25
- options[(key.to_sym rescue key) || key] = options.delete(key)
26
- end
27
-
28
- case method
29
- when 'smtp'
30
- setup_smtp options
31
- when 'sendmail'
32
- setup_sendmail
33
- when 'exim'
34
- setup_exim options
35
- end
36
- end
37
-
38
- def setup_smtp options = {}
39
- Mail.defaults do
40
- delivery_method :smtp, Idid::Configuration::SMTP_DEFAULTS.merge(options)
41
- end
42
- end
43
-
44
- def setup_sendmail
45
- Mail.defaults do
46
- delivery_method :sendmail
47
- end
48
- end
49
-
50
- def setup_exim options={}
51
- Mail.defaults do
52
- delivery_method :exim, Idid::Configuration::EXIM_DEFAULTS.merge(options)
53
- end
54
- end
55
- end
56
7
  end
@@ -6,23 +6,27 @@ describe Idid::Configuration do
6
6
  let(:project) { 'foobar' }
7
7
  let(:delivery) { {:method => :sendmail} }
8
8
 
9
- before { Idid::Configuration.any_instance.stub(:read_config) { nil } }
10
-
11
9
  its('project') { should eq project }
12
10
  its('email') { should eq email }
13
11
 
14
- it 'raises ArgumentError if no email option is passed' do
15
- expect { Idid::Configuration.new('project' => project, 'delivery' => delivery) }.
16
- to raise_error(ArgumentError, /email/)
17
- end
12
+ context "when any of the options are missing" do
13
+ before do
14
+ Idid::Configuration.any_instance.stub(:read_config) { nil }
15
+ end
18
16
 
19
- it 'raises ArgumentError if no project option is passed' do
20
- expect { Idid::Configuration.new('email' => email, 'delivery' => delivery) }.
21
- to raise_error(ArgumentError, /project/)
22
- end
17
+ it 'raises ArgumentError if no email option is passed' do
18
+ expect { Idid::Configuration.new('project' => project, 'delivery' => delivery) }.
19
+ to raise_error(ArgumentError, /email/)
20
+ end
21
+
22
+ it 'raises ArgumentError if no project option is passed' do
23
+ expect { Idid::Configuration.new('email' => email, 'delivery' => delivery) }.
24
+ to raise_error(ArgumentError, /project/)
25
+ end
23
26
 
24
- it 'raises ArgumentError if no delivery option is passed' do
25
- expect { Idid::Configuration.new('email' => email, 'project' => project) }.
26
- to raise_error(ArgumentError, /delivery/)
27
+ it 'raises ArgumentError if no delivery option is passed' do
28
+ expect { Idid::Configuration.new('email' => email, 'project' => project) }.
29
+ to raise_error(ArgumentError, /delivery/)
30
+ end
27
31
  end
28
32
  end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Idid::Delivery do
4
+
5
+ subject { delivery }
6
+
7
+ let(:delivery) { Idid::Delivery.new config }
8
+ let(:config) do
9
+ Idid::Configuration.new(
10
+ 'project' => 'foo',
11
+ 'email' => 'john@example.com',
12
+ 'delivery' => { 'method' => :test }
13
+ )
14
+ end
15
+
16
+ its('config') { should eq config }
17
+
18
+ describe "#email" do
19
+ subject { delivery.email 'Tested Idid::Deliver.email' }
20
+ its(:to) { should eq ['foo@team.idonethis.com'] }
21
+ its(:from) { should eq ['john@example.com'] }
22
+ its(:body) { should eq 'Tested Idid::Deliver.email' }
23
+ end
24
+
25
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe Idid::Task do
4
+ subject { task }
5
+
6
+ let(:task) { Idid::Task.new contents, logdate }
7
+ let(:contents) { 'Bar' }
8
+ let(:logdate) { Date.new 2013,1,1 }
9
+
10
+ its(:contents) { should eq contents }
11
+ its(:log) { should be_a_kind_of Hash }
12
+ its(:logdate) { should eq Date.new(2013,1,1) }
13
+
14
+ describe "#save" do
15
+ before do
16
+ Idid::Task.stub(:read_log).and_return log_file
17
+ Idid::Task.stub(:write_log).and_return true
18
+ task.save
19
+ end
20
+
21
+ subject { task.log }
22
+
23
+ context "date has no logged items yet" do
24
+ let(:log_file) { {"2013-02-01" => ["Foo"]} }
25
+ it { should eq({"2013-02-01" => ["Foo"], "2013-01-01" => ["Bar"]}) }
26
+ end
27
+
28
+ context "date has already logged items" do
29
+ let(:log_file) { {"2013-01-01" => ["Foo"]} }
30
+ it { should eq({"2013-01-01" => ["Foo", "Bar"]}) }
31
+ end
32
+ end
33
+
34
+ describe "#to_s" do
35
+ subject { task.to_s }
36
+ it { should eq contents }
37
+ end
38
+
39
+ describe ".list" do
40
+ before do
41
+ Idid::Task.stub(:read_log).and_return({"2013-01-01" => ["Foo", "Bar"]})
42
+ end
43
+
44
+ subject { Idid::Task.list date }
45
+
46
+ context "logged items exist" do
47
+ let(:date) { '2013-01-01' }
48
+ it { should match /Log for 1 January 2013/ }
49
+ it { should match /\* Foo/ }
50
+ it { should match /\* Bar/ }
51
+ end
52
+
53
+ context "no logged items" do
54
+ let(:date) { '2013-01-02' }
55
+ it { should match /Could not find any activity for 2 January 2013/ }
56
+ end
57
+ end
58
+
59
+ end
data/spec/spec_helper.rb CHANGED
@@ -2,3 +2,9 @@ require 'bundler'
2
2
  Bundler.require
3
3
 
4
4
  Dir[File.expand_path("../support/**/*.rb", __FILE__)].each {|f| require f}
5
+
6
+ RSpec.configure do |config|
7
+ config.color_enabled = true
8
+ config.tty = true
9
+ config.formatter = :progress
10
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: idid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-04 00:00:00.000000000 Z
12
+ date: 2013-01-08 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: rspec
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -27,6 +43,22 @@ dependencies:
27
43
  - - ~>
28
44
  - !ruby/object:Gem::Version
29
45
  version: 2.12.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: travis-lint
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
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: '0'
30
62
  - !ruby/object:Gem::Dependency
31
63
  name: mail
32
64
  requirement: !ruby/object:Gem::Requirement
@@ -43,6 +75,22 @@ dependencies:
43
75
  - - ~>
44
76
  - !ruby/object:Gem::Version
45
77
  version: 2.5.3
78
+ - !ruby/object:Gem::Dependency
79
+ name: json
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 1.7.5
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 1.7.5
46
94
  description: A Ruby CLI for iDoneThis
47
95
  email:
48
96
  - wrdevos@gmail.com
@@ -52,6 +100,7 @@ extensions: []
52
100
  extra_rdoc_files: []
53
101
  files:
54
102
  - .gitignore
103
+ - .travis.yml
55
104
  - Gemfile
56
105
  - LICENSE.txt
57
106
  - README.md
@@ -60,9 +109,13 @@ files:
60
109
  - idid.gemspec
61
110
  - lib/idid.rb
62
111
  - lib/idid/configuration.rb
112
+ - lib/idid/delivery.rb
63
113
  - lib/idid/interactive.rb
114
+ - lib/idid/task.rb
64
115
  - lib/idid/version.rb
65
116
  - spec/idid/configuration_spec.rb
117
+ - spec/idid/delivery_spec.rb
118
+ - spec/idid/task_spec.rb
66
119
  - spec/spec_helper.rb
67
120
  homepage: https://github.com/foxycoder/idid
68
121
  licenses: []
@@ -90,4 +143,6 @@ specification_version: 3
90
143
  summary: Post to iDoneThis from your command line.
91
144
  test_files:
92
145
  - spec/idid/configuration_spec.rb
146
+ - spec/idid/delivery_spec.rb
147
+ - spec/idid/task_spec.rb
93
148
  - spec/spec_helper.rb