launchy 2.2.0-java → 2.4.2-java
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 +7 -0
- data/CONTRIBUTING.md +11 -8
- data/HISTORY.md +154 -0
- data/Manifest.txt +3 -2
- data/{README.rdoc → README.md} +38 -24
- data/Rakefile +2 -2
- data/lib/launchy.rb +40 -14
- data/lib/launchy/applications/browser.rb +14 -13
- data/lib/launchy/argv.rb +36 -0
- data/lib/launchy/cli.rb +2 -4
- data/lib/launchy/descendant_tracker.rb +1 -1
- data/lib/launchy/detect/nix_desktop_environment.rb +24 -7
- data/lib/launchy/detect/runner.rb +15 -2
- data/lib/launchy/version.rb +1 -1
- data/spec/application_spec.rb +2 -2
- data/spec/applications/browser_spec.rb +3 -2
- data/spec/detect/nix_desktop_environment_spec.rb +6 -11
- data/spec/launchy_spec.rb +51 -4
- data/tasks/default.rake +76 -17
- data/tasks/this.rb +14 -7
- metadata +32 -44
- data/HISTORY.rdoc +0 -135
data/lib/launchy/argv.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Launchy
|
2
|
+
class Argv
|
3
|
+
attr_reader :argv
|
4
|
+
def initialize( *args )
|
5
|
+
@argv = args.flatten
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
@argv.join(' ')
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_str
|
13
|
+
to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](idx)
|
17
|
+
@argv[idx]
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid?
|
21
|
+
(not blank?) && executable?
|
22
|
+
end
|
23
|
+
|
24
|
+
def blank?
|
25
|
+
@argv.empty? || (@argv.first.strip.size == 0)
|
26
|
+
end
|
27
|
+
|
28
|
+
def executable?
|
29
|
+
::Launchy::Application.find_executable( @argv.first )
|
30
|
+
end
|
31
|
+
|
32
|
+
def ==( other )
|
33
|
+
@argv == other.argv
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/launchy/cli.rb
CHANGED
@@ -22,7 +22,7 @@ module Launchy
|
|
22
22
|
|
23
23
|
op.on( "-d", "--debug",
|
24
24
|
"Force debug. Output lots of information.") do |d|
|
25
|
-
@options[:debug] =
|
25
|
+
@options[:debug] = true
|
26
26
|
end
|
27
27
|
|
28
28
|
op.on( "-e", "--engine RUBY_ENGINE",
|
@@ -65,13 +65,11 @@ module Launchy
|
|
65
65
|
|
66
66
|
def good_run( argv, env )
|
67
67
|
if parse( argv, env ) then
|
68
|
-
Launchy.open( argv.shift, options )
|
68
|
+
Launchy.open( argv.shift, options ) { |e| error_output( e ) }
|
69
69
|
return true
|
70
70
|
else
|
71
71
|
return false
|
72
72
|
end
|
73
|
-
rescue StandardError => e
|
74
|
-
error_output( e )
|
75
73
|
end
|
76
74
|
|
77
75
|
def error_output( error )
|
@@ -19,7 +19,11 @@ module Launchy::Detect
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.fallback_browsers
|
22
|
-
%w[ firefox seamonkey opera mozilla netscape galeon ]
|
22
|
+
%w[ firefox seamonkey opera mozilla netscape galeon ].map { |x| ::Launchy::Argv.new( x ) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.browsers
|
26
|
+
[ browser, fallback_browsers ].flatten
|
23
27
|
end
|
24
28
|
|
25
29
|
#---------------------------------------
|
@@ -32,7 +36,7 @@ module Launchy::Detect
|
|
32
36
|
end
|
33
37
|
|
34
38
|
def self.browser
|
35
|
-
|
39
|
+
::Launchy::Argv.new( %w[ kfmclient openURL ] )
|
36
40
|
end
|
37
41
|
end
|
38
42
|
|
@@ -42,7 +46,7 @@ module Launchy::Detect
|
|
42
46
|
end
|
43
47
|
|
44
48
|
def self.browser
|
45
|
-
'gnome-open'
|
49
|
+
::Launchy::Argv.new( 'gnome-open' )
|
46
50
|
end
|
47
51
|
end
|
48
52
|
|
@@ -56,19 +60,32 @@ module Launchy::Detect
|
|
56
60
|
end
|
57
61
|
|
58
62
|
def self.browser
|
59
|
-
'exo-open'
|
63
|
+
::Launchy::Argv.new( 'exo-open' )
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Fall back environment as the last case
|
68
|
+
class Xdg < NixDesktopEnvironment
|
69
|
+
def self.is_current_desktop_environment?
|
70
|
+
Launchy::Application.find_executable( browser )
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.browser
|
74
|
+
::Launchy::Argv.new( 'xdg-open' )
|
60
75
|
end
|
61
76
|
end
|
62
77
|
|
63
|
-
|
78
|
+
# The one that is found when all else fails. And this must be declared last
|
79
|
+
class NotFound < NixDesktopEnvironment
|
64
80
|
def self.is_current_desktop_environment?
|
65
|
-
|
81
|
+
true
|
66
82
|
end
|
67
83
|
|
68
84
|
def self.browser
|
69
|
-
|
85
|
+
::Launchy::Argv.new
|
70
86
|
end
|
71
87
|
end
|
88
|
+
|
72
89
|
end
|
73
90
|
end
|
74
91
|
|
@@ -37,7 +37,7 @@ module Launchy::Detect
|
|
37
37
|
# and in that case system shell escaping rules are not done.
|
38
38
|
#
|
39
39
|
def shell_commands( cmd, args )
|
40
|
-
cmdline = [ cmd.shellsplit ]
|
40
|
+
cmdline = [ cmd.to_s.shellsplit ]
|
41
41
|
cmdline << args.flatten.collect{ |a| a.to_s }
|
42
42
|
return commandline_normalize( cmdline )
|
43
43
|
end
|
@@ -81,8 +81,21 @@ module Launchy::Detect
|
|
81
81
|
|
82
82
|
# escape the reserved shell characters in windows command shell
|
83
83
|
# http://technet.microsoft.com/en-us/library/cc723564.aspx
|
84
|
+
#
|
85
|
+
# Also make sure that the item after 'start' is guaranteed to be quoted.
|
86
|
+
# https://github.com/copiousfreetime/launchy/issues/62
|
84
87
|
def shell_commands( cmd, *args )
|
85
|
-
|
88
|
+
parts = cmd.shellsplit
|
89
|
+
|
90
|
+
if start_idx = parts.index('start') then
|
91
|
+
title_idx = start_idx + 1
|
92
|
+
title = parts[title_idx]
|
93
|
+
title = title.sub(/^/,'"') unless title[0] == '"'
|
94
|
+
title = title.sub(/$/,'"') unless title[-1] == '"'
|
95
|
+
parts[title_idx] = title
|
96
|
+
end
|
97
|
+
|
98
|
+
cmdline = [ parts ]
|
86
99
|
cmdline << args.flatten.collect { |a| a.to_s.gsub(/([&|()<>^])/, "^\\1") }
|
87
100
|
return commandline_normalize( cmdline )
|
88
101
|
end
|
data/lib/launchy/version.rb
CHANGED
data/spec/application_spec.rb
CHANGED
@@ -30,8 +30,8 @@ describe Launchy::Application do
|
|
30
30
|
lambda { Launchy::Application.handling( uri ) }.must_raise( Launchy::ApplicationNotFoundError )
|
31
31
|
end
|
32
32
|
|
33
|
-
it "can find open or curl" do
|
34
|
-
found = %w[ open curl ].any? do |app|
|
33
|
+
it "can find open or curl or xdg-open" do
|
34
|
+
found = %w[ open curl xdg-open ].any? do |app|
|
35
35
|
Launchy::Application.find_executable( app )
|
36
36
|
end
|
37
37
|
found.must_equal true
|
@@ -10,11 +10,12 @@ describe Launchy::Application::Browser do
|
|
10
10
|
after do
|
11
11
|
Launchy.reset_global_options
|
12
12
|
ENV.delete( 'KDE_FULL_SESSION' )
|
13
|
+
ENV.delete( 'BROWSER' )
|
13
14
|
end
|
14
15
|
|
15
|
-
{ 'windows' => 'start /b' ,
|
16
|
+
{ 'windows' => 'start "launchy" /b' ,
|
16
17
|
'darwin' => '/usr/bin/open',
|
17
|
-
'cygwin' => 'cmd /C start /b',
|
18
|
+
'cygwin' => 'cmd /C start "launchy" /b',
|
18
19
|
|
19
20
|
# when running these tests on a linux box, this test will fail
|
20
21
|
'linux' => nil }.each do |host_os, cmdline|
|
@@ -14,6 +14,8 @@ describe Launchy::Detect::NixDesktopEnvironment do
|
|
14
14
|
{ "KDE_FULL_SESSION" => Launchy::Detect::NixDesktopEnvironment::Kde,
|
15
15
|
"GNOME_DESKTOP_SESSION_ID" => Launchy::Detect::NixDesktopEnvironment::Gnome }.each_pair do |k,v|
|
16
16
|
it "can detect the desktop environment of a *nix machine using ENV[#{k}]" do
|
17
|
+
ENV.delete( "KDE_FULL_SESSION" )
|
18
|
+
ENV.delete( "GNOME_DESKTOP_SESSION_ID" )
|
17
19
|
ENV[k] = "launchy-test"
|
18
20
|
nix_env = Launchy::Detect::NixDesktopEnvironment.detect
|
19
21
|
nix_env.must_equal( v )
|
@@ -22,24 +24,17 @@ describe Launchy::Detect::NixDesktopEnvironment do
|
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
|
-
it "detects the fluxbox desktop environment" do
|
26
|
-
ENV['DESKTOP_SESSION'] = 'fluxbox'
|
27
|
-
fluxbox_env = Launchy::Detect::NixDesktopEnvironment.detect
|
28
|
-
fluxbox_env.must_equal( Launchy::Detect::NixDesktopEnvironment::Fluxbox )
|
29
|
-
fluxbox_env.browser.must_equal( Launchy::Detect::NixDesktopEnvironment::Fluxbox.browser )
|
30
|
-
ENV.delete( 'DESKTOP_SESSION' )
|
31
|
-
end
|
32
|
-
|
33
27
|
it "returns false for XFCE if xprop is not found" do
|
34
28
|
Launchy.host_os = "linux"
|
35
29
|
Launchy::Detect::NixDesktopEnvironment::Xfce.is_current_desktop_environment?.must_equal( false )
|
36
30
|
end
|
37
31
|
|
38
|
-
it "returns
|
32
|
+
it "returns NotFound if it cannot determine the *nix desktop environment" do
|
39
33
|
Launchy.host_os = "linux"
|
40
34
|
ENV.delete( "KDE_FULL_SESSION" )
|
41
35
|
ENV.delete( "GNOME_DESKTOP_SESSION_ID" )
|
42
|
-
Launchy::Detect::NixDesktopEnvironment.detect
|
36
|
+
not_found = Launchy::Detect::NixDesktopEnvironment.detect
|
37
|
+
not_found.must_equal( Launchy::Detect::NixDesktopEnvironment::NotFound )
|
38
|
+
not_found.browser.must_equal( Launchy::Argv.new )
|
43
39
|
end
|
44
|
-
|
45
40
|
end
|
data/spec/launchy_spec.rb
CHANGED
@@ -6,11 +6,15 @@ describe Launchy do
|
|
6
6
|
Launchy.reset_global_options
|
7
7
|
@stderr = $stderr
|
8
8
|
$stderr = StringIO.new
|
9
|
+
@stdout = $stdout
|
10
|
+
$stdout = StringIO.new
|
11
|
+
@invalid_url = 'blah://example.com/invalid'
|
9
12
|
end
|
10
13
|
|
11
14
|
after do
|
12
15
|
Launchy.reset_global_options
|
13
16
|
$stderr = @stderr
|
17
|
+
$stdout = @stdout
|
14
18
|
end
|
15
19
|
|
16
20
|
it "logs to stderr when LAUNCHY_DEBUG environment variable is set" do
|
@@ -23,16 +27,32 @@ describe Launchy do
|
|
23
27
|
ENV["LAUNCHY_DEBUG"] = nil
|
24
28
|
end
|
25
29
|
|
26
|
-
it "sets the global option :dry_run to
|
30
|
+
it "sets the global option :dry_run to true if LAUNCHY_DRY_RUN environment variable is 'true'" do
|
27
31
|
ENV['LAUNCHY_DRY_RUN'] = 'true'
|
28
32
|
Launchy.extract_global_options({})
|
29
|
-
Launchy.dry_run?.must_equal
|
33
|
+
Launchy.dry_run?.must_equal true
|
30
34
|
ENV['LAUNCHY_DRY_RUN'] = nil
|
31
35
|
end
|
32
36
|
|
37
|
+
it "sets the global option :debug to true if LAUNCHY_DEBUG environment variable is 'true'" do
|
38
|
+
ENV['LAUNCHY_DEBUG'] = 'true'
|
39
|
+
Launchy.extract_global_options({})
|
40
|
+
Launchy.debug?.must_equal true
|
41
|
+
ENV['LAUNCHY_DEBUG'] = nil
|
42
|
+
end
|
43
|
+
|
33
44
|
it "has the global option :debug" do
|
34
45
|
Launchy.extract_global_options( { :debug => 'true' } )
|
35
46
|
Launchy.debug?.must_equal true
|
47
|
+
Launchy.extract_global_options( { :debug => true } )
|
48
|
+
Launchy.debug?.must_equal true
|
49
|
+
end
|
50
|
+
|
51
|
+
it "has the global option :dry_run" do
|
52
|
+
Launchy.extract_global_options( { :dry_run => 'true' } )
|
53
|
+
Launchy.dry_run?.must_equal true
|
54
|
+
Launchy.extract_global_options( { :dry_run => true } )
|
55
|
+
Launchy.dry_run?.must_equal true
|
36
56
|
end
|
37
57
|
|
38
58
|
it "has the global option :application" do
|
@@ -51,10 +71,37 @@ describe Launchy do
|
|
51
71
|
end
|
52
72
|
|
53
73
|
it "raises an exception if no scheme is found for the given uri" do
|
54
|
-
lambda { Launchy.open(
|
74
|
+
lambda { Launchy.open( @invalid_url ) }.must_raise Launchy::ApplicationNotFoundError
|
75
|
+
end
|
76
|
+
|
77
|
+
it "asssumes we open a local file if we have an exception if we have an invalid scheme and a valid path" do
|
78
|
+
uri = "blah://example.com/#{__FILE__}"
|
79
|
+
Launchy.open( uri , :dry_run => true )
|
80
|
+
$stdout.string.strip.must_equal "/usr/bin/open #{uri}"
|
81
|
+
end
|
82
|
+
|
83
|
+
it "opens a local file if we have a drive letter and a valid path on windows" do
|
84
|
+
uri = "C:#{__FILE__}"
|
85
|
+
Launchy.open( uri, :dry_run => true, :host_os => 'windows' )
|
86
|
+
$stdout.string.strip.must_equal 'cmd /c start "launchy" /b ' + uri
|
87
|
+
end
|
88
|
+
|
89
|
+
it "calls the block if instead of raising an exception if there is an error" do
|
90
|
+
Launchy.open( @invalid_url ) { $stderr.puts "oops had an error opening #{@invalid_url}" }
|
91
|
+
$stderr.string.strip.must_equal "oops had an error opening #{@invalid_url}"
|
92
|
+
end
|
93
|
+
|
94
|
+
it "calls the block with the values passed to launchy and the error" do
|
95
|
+
options = { :dry_run => true }
|
96
|
+
Launchy.open( @invalid_url, :dry_run => true ) { |e| $stderr.puts "had an error opening #{@invalid_url} with options #{options}: #{e}" }
|
97
|
+
$stderr.string.strip.must_equal "had an error opening #{@invalid_url} with options #{options}: No application found to handle '#{@invalid_url}'"
|
98
|
+
end
|
99
|
+
|
100
|
+
it "raises the error in the called block" do
|
101
|
+
lambda { Launchy.open( @invalid_url ) { raise StandardError, "KABOOM!" } }.must_raise StandardError
|
55
102
|
end
|
56
103
|
|
57
|
-
[ 'www.example.com', 'www.example.com/foo/bar' ].each do |x|
|
104
|
+
[ 'www.example.com', 'www.example.com/foo/bar', "C:#{__FILE__}" ].each do |x|
|
58
105
|
it "picks a Browser for #{x}" do
|
59
106
|
app = Launchy.app_for_uri_string( x )
|
60
107
|
app.must_equal( Launchy::Application::Browser )
|
data/tasks/default.rake
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# vim: syntax=ruby
|
2
2
|
require 'rake/clean'
|
3
|
+
require 'digest'
|
3
4
|
#------------------------------------------------------------------------------
|
4
5
|
# If you want to Develop on this project just run 'rake develop' and you'll
|
5
6
|
# have all you need to get going. If you want to use bundler for development,
|
@@ -11,7 +12,7 @@ namespace :develop do
|
|
11
12
|
# gemspec.
|
12
13
|
task :default do
|
13
14
|
require 'rubygems/dependency_installer'
|
14
|
-
installer = Gem::DependencyInstaller.new
|
15
|
+
installer = ::Gem::DependencyInstaller.new
|
15
16
|
|
16
17
|
This.set_coverage_gem
|
17
18
|
|
@@ -30,7 +31,7 @@ namespace :develop do
|
|
30
31
|
# Create a Gemfile that just references the gemspec
|
31
32
|
file 'Gemfile' => :gemspec do
|
32
33
|
File.open( "Gemfile", "w+" ) do |f|
|
33
|
-
f.puts 'source
|
34
|
+
f.puts 'source "https://rubygems.org/"'
|
34
35
|
f.puts 'gemspec'
|
35
36
|
end
|
36
37
|
end
|
@@ -53,9 +54,12 @@ begin
|
|
53
54
|
require 'rake/testtask'
|
54
55
|
Rake::TestTask.new( :test ) do |t|
|
55
56
|
t.ruby_opts = %w[ -w -rubygems ]
|
56
|
-
t.libs = %w[ lib spec ]
|
57
|
-
t.pattern = "spec
|
57
|
+
t.libs = %w[ lib spec test ]
|
58
|
+
t.pattern = "{test,spec}/**/{test_*,*_spec}.rb"
|
58
59
|
end
|
60
|
+
|
61
|
+
task :test_requirements
|
62
|
+
task :test => :test_requirements
|
59
63
|
task :default => :test
|
60
64
|
rescue LoadError
|
61
65
|
This.task_warning( 'test' )
|
@@ -71,11 +75,12 @@ begin
|
|
71
75
|
RDoc::Task.new do |t|
|
72
76
|
t.markup = 'tomdoc'
|
73
77
|
t.rdoc_dir = 'doc'
|
74
|
-
t.main = 'README.
|
78
|
+
t.main = 'README.md'
|
75
79
|
t.title = "#{This.name} #{This.version}"
|
76
|
-
t.rdoc_files.include( '*.rdoc', '
|
80
|
+
t.rdoc_files.include( FileList['*.{rdoc,md,txt}'], FileList['ext/**/*.c'],
|
81
|
+
FileList['lib/**/*.rb'] )
|
77
82
|
end
|
78
|
-
rescue LoadError
|
83
|
+
rescue StandardError, LoadError
|
79
84
|
This.task_warning( 'rdoc' )
|
80
85
|
end
|
81
86
|
|
@@ -146,19 +151,70 @@ end
|
|
146
151
|
#------------------------------------------------------------------------------
|
147
152
|
# Fixme - look for fixmes and report them
|
148
153
|
#------------------------------------------------------------------------------
|
149
|
-
|
150
|
-
task :
|
151
|
-
|
152
|
-
|
154
|
+
namespace :fixme do
|
155
|
+
task :default => 'manifest:check' do
|
156
|
+
This.manifest.each do |file|
|
157
|
+
next if file == __FILE__
|
158
|
+
next unless file =~ %r/(txt|rb|md|rdoc|css|html|xml|css)\Z/
|
159
|
+
puts "FIXME: Rename #{file}" if file =~ /fixme/i
|
160
|
+
IO.readlines( file ).each_with_index do |line, idx|
|
161
|
+
prefix = "FIXME: #{file}:#{idx+1}".ljust(42)
|
162
|
+
puts "#{prefix} => #{line.strip}" if line =~ /fixme/i
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def fixme_project_root
|
168
|
+
This.project_path( '../fixme' )
|
169
|
+
end
|
170
|
+
|
171
|
+
def fixme_project_path( subtree )
|
172
|
+
fixme_project_root.join( subtree )
|
173
|
+
end
|
174
|
+
|
175
|
+
def local_fixme_files
|
176
|
+
This.manifest.select { |p| p =~ %r|^tasks/| }
|
177
|
+
end
|
153
178
|
|
154
|
-
|
179
|
+
def outdated_fixme_files
|
180
|
+
local_fixme_files.reject do |local|
|
181
|
+
upstream = fixme_project_path( local )
|
182
|
+
Digest::SHA256.file( local ) == Digest::SHA256.file( upstream )
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def fixme_up_to_date?
|
187
|
+
outdated_fixme_files.empty?
|
188
|
+
end
|
155
189
|
|
156
|
-
|
157
|
-
|
158
|
-
|
190
|
+
desc "See if the fixme tools are outdated"
|
191
|
+
task :outdated => :release_check do
|
192
|
+
if fixme_up_to_date? then
|
193
|
+
puts "Fixme files are up to date."
|
194
|
+
else
|
195
|
+
outdated_fixme_files.each do |f|
|
196
|
+
puts "#{f} is outdated"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
desc "Update outdated fixme files"
|
202
|
+
task :update => :release_check do
|
203
|
+
if fixme_up_to_date? then
|
204
|
+
puts "Fixme files are already up to date."
|
205
|
+
else
|
206
|
+
puts "Updating fixme files:"
|
207
|
+
outdated_fixme_files.each do |local|
|
208
|
+
upstream = fixme_project_path( local )
|
209
|
+
puts " * #{local}"
|
210
|
+
FileUtils.cp( upstream, local )
|
211
|
+
end
|
212
|
+
puts "Use your git commands as appropriate."
|
159
213
|
end
|
160
214
|
end
|
161
215
|
end
|
216
|
+
desc "Look for fixmes and report them"
|
217
|
+
task :fixme => "fixme:default"
|
162
218
|
|
163
219
|
#------------------------------------------------------------------------------
|
164
220
|
# Gem Specification
|
@@ -172,11 +228,14 @@ task :gemspec do
|
|
172
228
|
end
|
173
229
|
|
174
230
|
# the gemspec is also a dev artifact and should not be kept around.
|
175
|
-
CLOBBER << This.gemspec_file
|
231
|
+
CLOBBER << This.gemspec_file.to_s
|
232
|
+
|
233
|
+
# .rbc files from ruby 2.0
|
234
|
+
CLOBBER << FileList["**/*.rbc"]
|
176
235
|
|
177
236
|
# The standard gem packaging task, everyone has it.
|
178
237
|
require 'rubygems/package_task'
|
179
|
-
Gem::PackageTask.new( This.platform_gemspec ) do
|
238
|
+
::Gem::PackageTask.new( This.platform_gemspec ) do
|
180
239
|
# nothing
|
181
240
|
end
|
182
241
|
|