thundersnow 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'nokogiri', '~> 1.0'
4
+ gem 'htmlentities'
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", "~> 2.3.0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.2"
12
+ gem "rcov", ">= 0"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ git (1.2.5)
6
+ htmlentities (4.2.4)
7
+ jeweler (1.5.2)
8
+ bundler (~> 1.0.0)
9
+ git (>= 1.2.5)
10
+ rake
11
+ nokogiri (1.4.4)
12
+ rake (0.8.7)
13
+ rcov (0.9.9)
14
+ rspec (2.3.0)
15
+ rspec-core (~> 2.3.0)
16
+ rspec-expectations (~> 2.3.0)
17
+ rspec-mocks (~> 2.3.0)
18
+ rspec-core (2.3.1)
19
+ rspec-expectations (2.3.0)
20
+ diff-lcs (~> 1.1.2)
21
+ rspec-mocks (2.3.0)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ bundler (~> 1.0.0)
28
+ htmlentities
29
+ jeweler (~> 1.5.2)
30
+ nokogiri (~> 1.0)
31
+ rcov
32
+ rspec (~> 2.3.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Peter Brown
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,57 @@
1
+ h1. thundersnow
2
+
3
+ A Ruby based command-line utility for viewing the weather
4
+
5
+ h2. About
6
+
7
+ Inspired by some recent "thundersnow":http://en.wikipedia.org/wiki/Thundersnow in New England, I decided to
8
+ build a simple application to check the weather while I'm coding.
9
+
10
+ h2. Installation
11
+
12
+ Rubygem installation coming soon...
13
+
14
+ h2. Usage
15
+
16
+ <pre>
17
+ thundersnow 05401
18
+ </pre>
19
+
20
+ <pre>
21
+ thundersnow "burlington, vt"
22
+ </pre>
23
+
24
+ h2. Sample Output
25
+
26
+ This is how the current output looks, better formatting is coming.
27
+
28
+ <pre>
29
+ Weather forecast for Burlington, VT
30
+ -------------------------
31
+ Snow Showers
32
+ 33F / 1C
33
+ Wind: S at 3 mph
34
+ Humidity: 97%
35
+ -------------------------
36
+ Forecast for Mon
37
+ High: 35F / Low: 20F
38
+ Conditions: Snow
39
+ -------------------------
40
+ Forecast for Tue
41
+ High: 22F / Low: 4F
42
+ Conditions: Snow
43
+ -------------------------
44
+ Forecast for Wed
45
+ High: 22F / Low: 5F
46
+ Conditions: Snow Showers
47
+ -------------------------
48
+ Forecast for Thu
49
+ High: 18F / Low: 5F
50
+ Conditions: Partly Cloudy
51
+ </pre>
52
+
53
+ h2. Copyright
54
+
55
+ Copyright (c) 2011 Peter Brown. See LICENSE.txt for
56
+ further details.
57
+
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "thundersnow"
16
+ gem.homepage = "http://github.com/beerlington/thundersnow"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{Ruby based command-line utility for viewing the weather}
19
+ gem.description = %Q{Check the weather without leaving your terminal. Uses Google's weather API to provide current conditions and forecast weather information.}
20
+ gem.email = "github@lette.us"
21
+ gem.authors = ["Peter Brown"]
22
+ gem.executables = ["thundersnow"]
23
+ gem.add_runtime_dependency 'nokogiri', '~> 1.0'
24
+ gem.add_runtime_dependency 'htmlentities'
25
+ gem.add_development_dependency "rspec", "~> 2.3.0"
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rspec/core'
30
+ require 'rspec/core/rake_task'
31
+ RSpec::Core::RakeTask.new(:spec) do |spec|
32
+ spec.pattern = FileList['spec/**/*_spec.rb']
33
+ end
34
+
35
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
36
+ spec.pattern = 'spec/**/*_spec.rb'
37
+ spec.rcov = true
38
+ end
39
+
40
+ task :default => :spec
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "thundersnow #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/bin/thundersnow ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+ require 'thundersnow'
5
+
6
+ if ARGV.size == 0
7
+ puts 'Thundersnow Usage:'
8
+ puts 'Get weather for a zipcode: thundersnow 05401'
9
+ puts 'Get weather for a city, state: thundersnow "burlington, vt"'
10
+ else
11
+ Thundersnow.run ARGV
12
+ end
@@ -0,0 +1,115 @@
1
+ require 'nokogiri'
2
+ require 'open-uri'
3
+ require 'htmlentities'
4
+
5
+ class Thundersnow
6
+ class << self
7
+ def run(args)
8
+ @args = args
9
+
10
+ location = args.reject {|a| a =~ /^--/ }[0]
11
+
12
+ uri = URI.encode "http://www.google.com/ig/api?weather=#{location}"
13
+ @xml = Nokogiri::XML(open(uri))
14
+
15
+ # Invalid locations contain problem_cause xml tag
16
+ if @xml.xpath('//weather/problem_cause').size > 0
17
+ return puts "Could not locate weather for #{location}"
18
+ end
19
+
20
+ if show_forecast?
21
+ show :forecast
22
+ else
23
+ show :current
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def show(name)
30
+ puts send(name)
31
+ end
32
+
33
+ def show_forecast?
34
+ @args.detect {|a| a == '--forecast' }
35
+ end
36
+
37
+ def city
38
+ @city ||= read_attr(@xml, '//forecast_information/city')
39
+ end
40
+
41
+ def current
42
+ values = ["Current Conditions for #{city}"]
43
+ values << condition
44
+ values << temperatures
45
+ values << wind
46
+ values << humidity
47
+ values.join("\n")
48
+ end
49
+
50
+ def condition
51
+ read_attr(current_conditions, 'condition')
52
+ end
53
+
54
+ def temperatures
55
+ "#{temp_f} / #{temp_c}"
56
+ end
57
+
58
+ def wind
59
+ read_attr(current_conditions, 'wind_condition')
60
+ end
61
+
62
+ def humidity
63
+ read_attr(current_conditions, 'humidity')
64
+ end
65
+
66
+ def temp_f
67
+ read_attr(current_conditions, 'temp_f').to_s + deg_symbol + "F"
68
+ end
69
+
70
+ def temp_c
71
+ read_attr(current_conditions, 'temp_c').to_s + deg_symbol + 'C'
72
+ end
73
+
74
+ def deg_symbol
75
+ HTMLEntities.new.decode("&deg;")
76
+ end
77
+
78
+ def current_conditions
79
+ @current_conditions ||= @xml.xpath('//current_conditions')
80
+ end
81
+
82
+ def forecast
83
+ values = ["Weather Forecast for #{city}"]
84
+
85
+ @xml.xpath('//forecast_conditions').each do |day|
86
+ day_of_week = read_attr(day, 'day_of_week')
87
+ values << "Forecast for #{readable_day(day_of_week)}"
88
+ values << "High: #{read_attr(day, 'high')+deg_symbol}F / Low: #{read_attr(day, 'low')+deg_symbol}F"
89
+ values << "Conditions: #{read_attr(day, 'condition')}"
90
+ values << "-------------------------"
91
+ end
92
+
93
+ values.join("\n")
94
+ end
95
+
96
+ def readable_day(day_of_week)
97
+ return "Today" if day_of_week == today
98
+ return "Tomorrow" if day_of_week == tomorrow
99
+ day_of_week
100
+ end
101
+
102
+ def today
103
+ Time.now.strftime('%a')
104
+ end
105
+
106
+ def tomorrow
107
+ (Time.now + 86400).strftime('%a')
108
+ end
109
+
110
+ def read_attr(root, node)
111
+ root.xpath(node).attribute('data').to_s
112
+ end
113
+ end
114
+
115
+ end
@@ -0,0 +1,33 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'thundersnow'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
13
+
14
+ ZIP = "05401"
15
+
16
+ XML = '<?xml version="1.0"?>
17
+ <xml_api_reply version="1"><weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0" >
18
+ <forecast_information><city data="Burlington, VT"/><postal_code data="05401"/><latitude_e6 data=""/><longitude_e6 data=""/><forecast_date data="2011-02-07"/>
19
+ <current_date_time data="2011-02-08 03:19:38 +0000"/><unit_system data="US"/></forecast_information><current_conditions>
20
+ <condition data="Snow Showers"/><temp_f data="34"/><temp_c data="1"/><humidity data="Humidity: 87%"/><icon data="/ig/images/weather/snow.gif"/>
21
+ <wind_condition data="Wind: S at 6 mph"/></current_conditions><forecast_conditions><day_of_week data="Mon"/><low data="20"/><high data="35"/>
22
+ <icon data="/ig/images/weather/snow.gif"/><condition data="Snow"/></forecast_conditions><forecast_conditions><day_of_week data="Tue"/><low data="4"/>
23
+ <high data="22"/><icon data="/ig/images/weather/snow.gif"/><condition data="Snow"/></forecast_conditions><forecast_conditions><day_of_week data="Wed"/>
24
+ <low data="5"/><high data="22"/><icon data="/ig/images/weather/snow.gif"/><condition data="Snow Showers"/></forecast_conditions><forecast_conditions>
25
+ <day_of_week data="Thu"/><low data="5"/><high data="18"/><icon data="/ig/images/weather/partly_cloudy.gif"/><condition data="Partly Cloudy"/>
26
+ </forecast_conditions></weather></xml_api_reply>'
27
+
28
+
29
+ BAD_XML = '<?xml version="1.0"?>
30
+ <xml_api_reply version="1">
31
+ <weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0" >
32
+ <problem_cause data=""/>
33
+ </weather></xml_api_reply>'
@@ -0,0 +1,80 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Thundersnow do
4
+ before do
5
+ Thundersnow.stub(:open).and_return(XML)
6
+ Thundersnow.stub(:show).and_return(true)
7
+ end
8
+
9
+ context "for current conditions" do
10
+ before do
11
+ @args = [ZIP]
12
+ end
13
+
14
+ context "when running" do
15
+
16
+ it "should set the @xml instance variable" do
17
+ Thundersnow.run @args
18
+ Thundersnow.instance_variable_get('@xml').to_s.should == Nokogiri::XML(XML).to_s
19
+ end
20
+
21
+ it "should show the current conditions" do
22
+ Thundersnow.should_receive(:show).with(:current).once
23
+ Thundersnow.run @args
24
+ end
25
+
26
+ it "should not show the forecast conditions" do
27
+ Thundersnow.should_not_receive(:show).with(:forecast)
28
+ Thundersnow.run @args
29
+ end
30
+ end
31
+ end
32
+
33
+ context "for forecast conditions" do
34
+ before do
35
+ @args = [ZIP, '--forecast']
36
+ end
37
+
38
+ context "when running" do
39
+
40
+ it "should set the @xml instance variable" do
41
+ Thundersnow.run @args
42
+ Thundersnow.instance_variable_get('@xml').to_s.should == Nokogiri::XML(XML).to_s
43
+ end
44
+
45
+ it "should show the forecast conditions" do
46
+ Thundersnow.should_receive(:show).with(:forecast).once
47
+ Thundersnow.run @args
48
+ end
49
+
50
+ it "should not show the current conditions" do
51
+ Thundersnow.should_not_receive(:show).with(:current)
52
+ Thundersnow.run @args
53
+ end
54
+ end
55
+ end
56
+
57
+ context "w/ invalid location" do
58
+ before do
59
+ Thundersnow.stub(:open).and_return(BAD_XML)
60
+ end
61
+
62
+ context "when running" do
63
+ before do
64
+ Thundersnow.stub(:show).and_return(true)
65
+ @args = [ZIP]
66
+ end
67
+
68
+ it "should set the @xml instance variable" do
69
+ Thundersnow.run @args
70
+ Thundersnow.instance_variable_get('@xml').to_s.should == Nokogiri::XML(BAD_XML).to_s
71
+ end
72
+
73
+ it "should return and not show anything" do
74
+ Thundersnow.should_not_receive(:show)
75
+ Thundersnow.run @args
76
+ end
77
+ end
78
+ end
79
+
80
+ end
metadata ADDED
@@ -0,0 +1,170 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thundersnow
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Peter Brown
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-02-08 00:00:00 -05:00
14
+ default_executable: thundersnow
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: nokogiri
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: "1.0"
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: htmlentities
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: rspec
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 2.3.0
46
+ type: :development
47
+ prerelease: false
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: bundler
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: 1.0.0
57
+ type: :development
58
+ prerelease: false
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: jeweler
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: 1.5.2
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
72
+ name: rcov
73
+ requirement: &id006 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: *id006
82
+ - !ruby/object:Gem::Dependency
83
+ name: nokogiri
84
+ requirement: &id007 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: "1.0"
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: *id007
93
+ - !ruby/object:Gem::Dependency
94
+ name: htmlentities
95
+ requirement: &id008 !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: "0"
101
+ type: :runtime
102
+ prerelease: false
103
+ version_requirements: *id008
104
+ - !ruby/object:Gem::Dependency
105
+ name: rspec
106
+ requirement: &id009 !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ~>
110
+ - !ruby/object:Gem::Version
111
+ version: 2.3.0
112
+ type: :development
113
+ prerelease: false
114
+ version_requirements: *id009
115
+ description: Check the weather without leaving your terminal. Uses Google's weather API to provide current conditions and forecast weather information.
116
+ email: github@lette.us
117
+ executables:
118
+ - thundersnow
119
+ extensions: []
120
+
121
+ extra_rdoc_files:
122
+ - LICENSE.txt
123
+ - README.textile
124
+ files:
125
+ - .document
126
+ - .rspec
127
+ - Gemfile
128
+ - Gemfile.lock
129
+ - LICENSE.txt
130
+ - README.textile
131
+ - Rakefile
132
+ - VERSION
133
+ - bin/thundersnow
134
+ - lib/thundersnow.rb
135
+ - spec/spec_helper.rb
136
+ - spec/thundersnow_spec.rb
137
+ has_rdoc: true
138
+ homepage: http://github.com/beerlington/thundersnow
139
+ licenses:
140
+ - MIT
141
+ post_install_message:
142
+ rdoc_options: []
143
+
144
+ require_paths:
145
+ - lib
146
+ required_ruby_version: !ruby/object:Gem::Requirement
147
+ none: false
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ hash: 2985694618793645140
152
+ segments:
153
+ - 0
154
+ version: "0"
155
+ required_rubygems_version: !ruby/object:Gem::Requirement
156
+ none: false
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: "0"
161
+ requirements: []
162
+
163
+ rubyforge_project:
164
+ rubygems_version: 1.5.0
165
+ signing_key:
166
+ specification_version: 3
167
+ summary: Ruby based command-line utility for viewing the weather
168
+ test_files:
169
+ - spec/spec_helper.rb
170
+ - spec/thundersnow_spec.rb