launchy 2.0.3 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY CHANGED
@@ -1,4 +1,11 @@
1
1
  = Launchy Changlog
2
+ == Version 2.0.4 - 2011-07-23
3
+
4
+ * Fix windows 'start' commandline (copiousfreetime/launchy#5)
5
+ * Add capability to open local files with no file: scheme present (copiousfreetime/launchy#29)
6
+ * Added 'rake how_to_contribute' task (copiousfreetime/launchy#30)
7
+ * Make better decisions on when to do shell escaping (copiousfreetime/launchy#31)
8
+ * Switch to Addressable::URI so UTF-8 urls may be parsed. (copiousfreetime/launchy#32)
2
9
 
3
10
  == Version 2.0.3 - 2011-07-17
4
11
 
data/README CHANGED
@@ -47,6 +47,38 @@ An example of using the public API:
47
47
 
48
48
  Launchy.open( "http://www.ruby-lang.org" )
49
49
 
50
+ == UPGRADING
51
+
52
+ The previously published version of Launchy was 0.4.0. There have been so many
53
+ changes, and a mistaken tag at 1.0.0, that I have decided to bump all the way
54
+ to 2.0.x.
55
+
56
+ I have attempted to keep backward compatibility with the previous examples. The
57
+ previous API examples of:
58
+
59
+ Launchy::Browser.run("http://www.ruby-lang.org/")
60
+
61
+ and
62
+
63
+ Launchy::Browser.new.visit("http://www.ruby-lang.org/")
64
+
65
+ will still work, and you will get a deprecation notice, along with the line
66
+ of code you should probably update. For example, this is what would print out
67
+ in the github gem if it was updated to use 2.0.x but not use the supported API.
68
+
69
+ % gh home
70
+ WARNING: You made a call to a deprecated Launchy API. This call should be changed to 'Launchy.open( uri )'
71
+ WARNING: I think I was able to find the location that needs to be fixed. Please go look at:
72
+ WARNING:
73
+ WARNING: /Users/jeremy/.rvm/gems/ruby-1.8.7-p334/gems/github-0.6.2/lib/commands/helpers.rb:275:in `open'
74
+ WARNING: helper :open do |url|
75
+ WARNING: has_launchy? proc {
76
+ WARNING: Launchy::Browser.new.visit url
77
+ WARNING: }
78
+ WARNING: end
79
+ WARNING:
80
+ WARNING: If this is not the case, please file a bug. Please file a bug at https://github.com/copiousfreetime/launchy/issues/new
81
+
50
82
  == ISC LICENSE
51
83
 
52
84
  http://opensource.org/licenses/isc-license.txt
data/Rakefile CHANGED
@@ -4,9 +4,11 @@
4
4
  #++
5
5
 
6
6
  begin
7
+ USING_BONES_VERSION = '3.7.0'
7
8
  require 'bones'
8
9
  rescue LoadError
9
- abort '### Please install the "bones" gem ###'
10
+ load 'tasks/contribute.rake'
11
+ Rake.application.invoke_task( :help )
10
12
  end
11
13
 
12
14
  task :default => 'test:run'
@@ -42,18 +44,27 @@ _
42
44
 
43
45
  if RUBY_PLATFORM == "java" then
44
46
  depend_on "spoon" , "~> 0.0.1"
47
+ depend_on 'ffi' , "~> 1.0.9"
45
48
  gem.extras = { :platform => Gem::Platform.new( "java" ) }
46
49
  end
47
50
 
51
+ depend_on "addressable", "~> 2.2.6"
52
+
48
53
  depend_on "rake" , "~> 0.9.2", :development => true
49
54
  depend_on "minitest" , "~> 2.3.1", :development => true
50
- depend_on 'bones' , "~> 3.7.0", :development => true
55
+ depend_on 'bones' , "~> #{USING_BONES_VERSION}", :development => true
51
56
  depend_on 'bones-rcov', "~> 1.0.1", :development => true
52
57
  depend_on 'rcov' , "~> 0.9.9", :development => true
53
58
  depend_on "spoon" , "~> 0.0.1", :development => true
59
+ depend_on 'ffi' , "~> 1.0.9", :development => true
54
60
 
55
61
  test.files = FileList["spec/**/*_spec.rb"]
56
62
  test.opts << "-w -Ilib:spec"
57
63
 
58
64
  rcov.opts << "--exclude gems"
59
65
  }
66
+
67
+ # Sorry Tim, I need to manage my own bones version
68
+ ::Bones.config.gem._spec.dependencies.delete_if do |d|
69
+ d.name == 'bones' and d.requirement.to_s =~ /^>=/
70
+ end
@@ -1,4 +1,4 @@
1
- require 'uri'
1
+ require 'addressable/uri'
2
2
 
3
3
  #
4
4
  # The entry point into Launchy. This is the sole supported public API.
@@ -25,8 +25,8 @@ module Launchy
25
25
  def open(uri, options = {} )
26
26
  begin
27
27
  extract_global_options( options )
28
- uri = URI.parse( uri )
29
- app = Launchy::Application.for_scheme( uri )
28
+ uri = Addressable::URI.parse( uri )
29
+ app = Launchy::Application.handling( uri )
30
30
  app.new.open( uri, options )
31
31
  rescue Exception => e
32
32
  msg = "Failure in opening #{uri} with options #{options.inspect}: #{e}"
@@ -9,39 +9,19 @@ module Launchy
9
9
  # 1. A constructor taking no parameters
10
10
  # 2. An instance method 'open' taking a string or URI as the first parameter and a
11
11
  # hash as the second
12
- # 3. A class method 'schemes' that returns an array of Strings containing the
13
- # schemes that the Application will handle
12
+ # 3. A class method 'handles?' that takes a String and returns true if that
13
+ # class can handle the input.
14
14
  class Application
15
15
  extend DescendantTracker
16
16
 
17
17
  class << self
18
+ # Find the application that handles the given uri.
18
19
  #
19
- # The list of all the schemes all the applications know
20
- #
21
- def scheme_list
22
- children.collect { |a| a.schemes }.flatten.sort
23
- end
24
-
25
- #
26
- # if this application handles the given scheme
27
- #
28
- def handles?( scheme )
29
- schemes.include?( scheme )
30
- end
31
-
32
- #
33
- # Find the application that handles the given scheme. May take either a
34
- # String or something that responds_to?( :scheme )
35
- #
36
- def for_scheme( scheme )
37
- if scheme.respond_to?( :scheme ) then
38
- scheme = scheme.scheme
39
- end
40
-
41
- klass = find_child( :handles?, scheme )
20
+ # returns the Class that can handle the uri
21
+ def handling( uri )
22
+ klass = find_child( :handles?, uri )
42
23
  return klass if klass
43
-
44
- raise SchemeNotFoundError, "No application found to handle scheme '#{scheme}'. Known schemes: #{scheme_list.join(", ")}"
24
+ raise ApplicationNotFoundError, "No application found to handle '#{uri}'"
45
25
  end
46
26
 
47
27
  #
@@ -7,12 +7,17 @@ class Launchy::Application
7
7
  %w[ http https ftp file ]
8
8
  end
9
9
 
10
+ def self.handles?( uri )
11
+ return true if schemes.include?( uri.scheme )
12
+ return true if File.exist?( uri.path )
13
+ end
14
+
10
15
  def windows_app_list
11
- [ 'start "Launchy" /d']
16
+ [ 'start /b' ]
12
17
  end
13
18
 
14
19
  def cygwin_app_list
15
- [ 'cmd /C start "Launchy" /d' ]
20
+ [ 'cmd /C start /b' ]
16
21
  end
17
22
 
18
23
  def darwin_app_list
@@ -34,18 +34,19 @@ module Launchy::Detect
34
34
  #
35
35
  # cut it down to just the shell commands that will be passed to exec or
36
36
  # posix_spawn. The cmd argument is split according to shell rules and the
37
- # args are escaped according to shell rules.
37
+ # args are not escaped because they whole set is passed to system as *args
38
+ # and in that case system shell escaping rules are not done.
38
39
  #
39
40
  def shell_commands( cmd, args )
40
41
  cmdline = [ cmd.shellsplit ]
41
- cmdline << args.flatten.collect{ |a| a.to_s.shellescape }
42
+ cmdline << args.flatten.collect{ |a| a.to_s }
42
43
  return commandline_normalize( cmdline )
43
44
  end
44
45
 
45
46
  def commandline_normalize( cmdline )
46
47
  c = cmdline.flatten!
47
48
  c = c.find_all { |a| (not a.nil?) and ( a.size > 0 ) }
48
- Launchy.log "ARGV => #{c.inspect}"
49
+ Launchy.log "commandline_normalized => #{c.join(' ')}"
49
50
  return c
50
51
  end
51
52
 
@@ -69,16 +70,20 @@ module Launchy::Detect
69
70
  class Windows < Runner
70
71
 
71
72
  def all_args( cmd, *args )
72
- [ 'cmd', '/c', *shell_commands( cmd, *args ) ]
73
+ args = [ 'cmd', '/c', *shell_commands( cmd, *args ) ]
74
+ Launchy.log "Windows: all_args => #{args.inspect}"
75
+ return args
73
76
  end
74
77
 
75
78
  def dry_run( cmd, *args )
76
79
  all_args( cmd, *args ).join(" ")
77
80
  end
78
81
 
82
+ # escape the reserved shell characters in windows command shell
83
+ # http://technet.microsoft.com/en-us/library/cc723564.aspx
79
84
  def shell_commands( cmd, *args )
80
- cmdline = [ cmd ]
81
- cmdline << args.flatten.collect { |a| a.to_s.gsub("&", "^&") }
85
+ cmdline = [ cmd.shellsplit ]
86
+ cmdline << args.flatten.collect { |a| a.to_s.gsub(/([&|()<>^])/, "^\\1") }
82
87
  return commandline_normalize( cmdline )
83
88
  end
84
89
 
@@ -1,4 +1,4 @@
1
1
  module Launchy
2
2
  class Error < ::StandardError; end
3
- class SchemeNotFoundError < Error; end
3
+ class ApplicationNotFoundError < Error; end
4
4
  end
@@ -1,5 +1,5 @@
1
1
  module Launchy
2
- VERSION = "2.0.3"
2
+ VERSION = "2.0.4"
3
3
 
4
4
  module Version
5
5
 
@@ -1,17 +1,17 @@
1
1
  require 'spec_helper'
2
- require 'mock_scheme'
2
+ require 'mock_application'
3
3
 
4
4
  class JunkApp < Launchy::Application
5
- def self.schemes
6
- %w[ junk ]
5
+ def self.handles?( uri )
6
+ uri.scheme == "junk"
7
7
  end
8
8
  end
9
9
 
10
10
  describe Launchy::Application do
11
11
  it 'registers inherited classes' do
12
12
  class Junk2App < Launchy::Application
13
- def self.schemes
14
- %w[ junk2 ]
13
+ def self.handles?( uri )
14
+ uri.scheme == "junk2"
15
15
  end
16
16
  end
17
17
  Launchy::Application.children.must_include( Junk2App )
@@ -20,12 +20,14 @@ describe Launchy::Application do
20
20
 
21
21
  it "can find an app" do
22
22
  Launchy::Application.children.must_include( JunkApp )
23
- Launchy::Application.scheme_list.size.must_equal 7
24
- Launchy::Application.for_scheme( "junk" ).must_equal( JunkApp )
23
+ Launchy::Application.children.size.must_equal 3
24
+ uri = Addressable::URI.parse( "junk:///foo" )
25
+ Launchy::Application.handling( uri ).must_equal( JunkApp )
25
26
  end
26
27
 
27
28
  it "raises an error if an application cannot be found for the given scheme" do
28
- lambda { Launchy::Application.for_scheme( "foo" ) }.must_raise( Launchy::SchemeNotFoundError )
29
+ uri = Addressable::URI.parse( "foo:///bar" )
30
+ lambda { Launchy::Application.handling( uri ) }.must_raise( Launchy::ApplicationNotFoundError )
29
31
  end
30
32
 
31
33
  it "can find open or curl" do
@@ -12,9 +12,9 @@ describe Launchy::Application::Browser do
12
12
  ENV.delete( 'KDE_FULL_SESSION' )
13
13
  end
14
14
 
15
- { 'windows' => 'start "Launchy" /d' ,
15
+ { 'windows' => 'start /b' ,
16
16
  'darwin' => '/usr/bin/open',
17
- 'cygwin' => 'cmd /C start "Launchy" /d',
17
+ 'cygwin' => 'cmd /C start /b',
18
18
 
19
19
  # when running these tests on a linux box, this test will fail
20
20
  'linux' => nil }.each do |host_os, cmdline|
@@ -35,5 +35,10 @@ describe Launchy::Application::Browser do
35
35
  args.must_equal []
36
36
  end
37
37
  end
38
+
39
+ it "handles a file on the file system when there is no file:// scheme" do
40
+ uri = Addressable::URI.parse( __FILE__ )
41
+ Launchy::Application::Browser.handles?( uri ).must_equal true
42
+ end
38
43
  end
39
44
 
@@ -62,18 +62,37 @@ describe Launchy::Detect::Runner do
62
62
  cmd.must_equal 'cmd /c not-really http://example.com'
63
63
  end
64
64
 
65
- it "Windows escapes '&' in urls" do
66
- win = Launchy::Detect::Runner::Windows.new
67
- win.all_args( "not-really", [ @test_url ] ).must_equal [ 'cmd', '/c', 'not-really', 'http://example.com/?foo=bar^&baz=wibble' ]
65
+ %w[ & | ( ) < > ^ ].each do |reserved_char|
66
+ it "Windows escapes '#{reserved_char}' in urls" do
67
+ win = Launchy::Detect::Runner::Windows.new
68
+ parts = [ 'http://example.com/?foo=bar', 'baz=wibble' ]
69
+ url = parts.join( reserved_char )
70
+ output_url = parts.join( "^#{reserved_char}" )
71
+
72
+ win.all_args( "not-really", [ url ] ).must_equal [ 'cmd', '/c', 'not-really', output_url ]
68
73
 
69
- cmd = win.dry_run( "not-really", [ @test_url ] )
70
- cmd.must_equal 'cmd /c not-really http://example.com/?foo=bar^&baz=wibble'
74
+ cmd = win.dry_run( "not-really", [ url ] )
75
+ cmd.must_equal "cmd /c not-really #{output_url}"
76
+ end
71
77
  end
72
78
 
73
- it "Jruby escapes '&' in urls" do
79
+ it "Jruby doesnot escapes '&' in urls" do
74
80
  jruby = Launchy::Detect::Runner::Jruby.new
75
81
  cmd = jruby.dry_run( "not-really", [ @test_url ])
76
- cmd.must_equal 'not-really http://example.com/\\?foo\\=bar\\&baz\\=wibble'
82
+ cmd.must_equal 'not-really http://example.com/?foo=bar&baz=wibble'
83
+ end
84
+
85
+ it "does not escape %38 items in urls" do
86
+ l = Launchy::Detect::Runner::Forkable.new
87
+ cmd = l.dry_run( "not-really", [ "http://ja.wikipedia.org/wiki/%E3%81%82" ] )
88
+ cmd.must_equal( 'not-really http://ja.wikipedia.org/wiki/%E3%81%82' )
89
+ end
90
+
91
+ it "can launch a utf8 url" do
92
+ url = "http://ja.wikipedia.org/wiki/あ"
93
+ l = Launchy::Detect::Runner::Forkable.new
94
+ cmd = l.dry_run( "not-really", [ url ] )
95
+ cmd.must_equal( "not-really #{url}" )
77
96
  end
78
97
 
79
98
  end
@@ -0,0 +1,9 @@
1
+ class MockApplication < Launchy::Application
2
+ def self.schemes
3
+ %w[ mock mockother ]
4
+ end
5
+
6
+ def self.handles?( uri )
7
+ schemes.include?( uri.scheme )
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ namespace :bundle do
2
+
3
+ file 'Gemfile' => [ 'gem:spec' ] do
4
+ File.open( 'Gemfile', 'w+' ) do |f|
5
+ f.puts 'source "http://rubygems.org"'
6
+ f.puts 'gemspec'
7
+ end
8
+ end
9
+
10
+ desc "Create a bundler Gemfile"
11
+ task :gemfile => 'Gemfile'
12
+
13
+ end
@@ -0,0 +1,36 @@
1
+ desc "Instructions on how to contribute to launchy"
2
+ task :help do
3
+ abort <<-_banner
4
+ -----------------------------------------------------------------------
5
+ I see you are wanting to do some development on launchy. You will
6
+ need to install the 'bones' gem first.
7
+
8
+ % gem install bones -v #{USING_BONES_VERSION}
9
+
10
+ The easiest way to start after that is with the
11
+ 'install:dependencies' task:
12
+
13
+ % rake gem:install_dependencies
14
+
15
+ If you use bundler, then you will need to first create the Gemfile
16
+ and then run 'bundle install':
17
+
18
+ % rake bundle:gemfile
19
+ % bundle install
20
+
21
+ Now you are ready to work on launchy. Please submit bugs and pull
22
+ requests to:
23
+
24
+ https://github.com/copiousfreetime/launchy
25
+
26
+ Thanks!
27
+
28
+ -jeremy
29
+ -----------------------------------------------------------------------
30
+ _banner
31
+ end
32
+
33
+ desc "(Alias for 'help') Instructions on how to contribute to launchy"
34
+ task 'how_to_contribute' => :help
35
+ desc "(Alias for 'help') Instructions on how to contribute to launchy"
36
+ task '==> I WANT TO CONTRIBUTE <==' => :help
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: launchy
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
4
+ hash: 7
5
5
  prerelease:
6
6
  segments:
7
7
  - 2
8
8
  - 0
9
- - 3
10
- version: 2.0.3
9
+ - 4
10
+ version: 2.0.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jeremy Hinegardner
@@ -15,13 +15,29 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-07-17 00:00:00 -06:00
18
+ date: 2011-07-23 00:00:00 -06:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: rake
22
+ name: addressable
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 11
30
+ segments:
31
+ - 2
32
+ - 2
33
+ - 6
34
+ version: 2.2.6
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rake
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
25
41
  none: false
26
42
  requirements:
27
43
  - - ~>
@@ -33,11 +49,11 @@ dependencies:
33
49
  - 2
34
50
  version: 0.9.2
35
51
  type: :development
36
- version_requirements: *id001
52
+ version_requirements: *id002
37
53
  - !ruby/object:Gem::Dependency
38
54
  name: minitest
39
55
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
56
+ requirement: &id003 !ruby/object:Gem::Requirement
41
57
  none: false
42
58
  requirements:
43
59
  - - ~>
@@ -49,11 +65,11 @@ dependencies:
49
65
  - 1
50
66
  version: 2.3.1
51
67
  type: :development
52
- version_requirements: *id002
68
+ version_requirements: *id003
53
69
  - !ruby/object:Gem::Dependency
54
70
  name: bones
55
71
  prerelease: false
56
- requirement: &id003 !ruby/object:Gem::Requirement
72
+ requirement: &id004 !ruby/object:Gem::Requirement
57
73
  none: false
58
74
  requirements:
59
75
  - - ~>
@@ -65,11 +81,11 @@ dependencies:
65
81
  - 0
66
82
  version: 3.7.0
67
83
  type: :development
68
- version_requirements: *id003
84
+ version_requirements: *id004
69
85
  - !ruby/object:Gem::Dependency
70
86
  name: bones-rcov
71
87
  prerelease: false
72
- requirement: &id004 !ruby/object:Gem::Requirement
88
+ requirement: &id005 !ruby/object:Gem::Requirement
73
89
  none: false
74
90
  requirements:
75
91
  - - ~>
@@ -81,11 +97,11 @@ dependencies:
81
97
  - 1
82
98
  version: 1.0.1
83
99
  type: :development
84
- version_requirements: *id004
100
+ version_requirements: *id005
85
101
  - !ruby/object:Gem::Dependency
86
102
  name: rcov
87
103
  prerelease: false
88
- requirement: &id005 !ruby/object:Gem::Requirement
104
+ requirement: &id006 !ruby/object:Gem::Requirement
89
105
  none: false
90
106
  requirements:
91
107
  - - ~>
@@ -97,11 +113,11 @@ dependencies:
97
113
  - 9
98
114
  version: 0.9.9
99
115
  type: :development
100
- version_requirements: *id005
116
+ version_requirements: *id006
101
117
  - !ruby/object:Gem::Dependency
102
118
  name: spoon
103
119
  prerelease: false
104
- requirement: &id006 !ruby/object:Gem::Requirement
120
+ requirement: &id007 !ruby/object:Gem::Requirement
105
121
  none: false
106
122
  requirements:
107
123
  - - ~>
@@ -113,23 +129,23 @@ dependencies:
113
129
  - 1
114
130
  version: 0.0.1
115
131
  type: :development
116
- version_requirements: *id006
132
+ version_requirements: *id007
117
133
  - !ruby/object:Gem::Dependency
118
- name: bones
134
+ name: ffi
119
135
  prerelease: false
120
- requirement: &id007 !ruby/object:Gem::Requirement
136
+ requirement: &id008 !ruby/object:Gem::Requirement
121
137
  none: false
122
138
  requirements:
123
- - - ">="
139
+ - - ~>
124
140
  - !ruby/object:Gem::Version
125
- hash: 27
141
+ hash: 5
126
142
  segments:
127
- - 3
128
- - 7
143
+ - 1
129
144
  - 0
130
- version: 3.7.0
145
+ - 9
146
+ version: 1.0.9
131
147
  type: :development
132
- version_requirements: *id007
148
+ version_requirements: *id008
133
149
  description: |
134
150
  Launchy is helper class for launching cross-platform applications in a
135
151
  fire and forget manner.
@@ -180,10 +196,12 @@ files:
180
196
  - spec/detect/ruby_engine_spec.rb
181
197
  - spec/detect/runner_spec.rb
182
198
  - spec/launchy_spec.rb
183
- - spec/mock_scheme.rb
199
+ - spec/mock_application.rb
184
200
  - spec/spec_helper.rb
185
201
  - spec/tattle-host-os.yaml
186
202
  - spec/version_spec.rb
203
+ - tasks/bundler.rake
204
+ - tasks/contribute.rake
187
205
  has_rdoc: true
188
206
  homepage: http://www.copiousfreetime.org/projects/launchy
189
207
  licenses: []
@@ -1,5 +0,0 @@
1
- class MockScheme < Launchy::Application
2
- def self.schemes
3
- %w[ mock mockother ]
4
- end
5
- end