launchy 0.4.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.autotest +28 -0
  2. data/HISTORY +15 -0
  3. data/LICENSE +1 -1
  4. data/NOTES +1 -0
  5. data/README +6 -6
  6. data/Rakefile +47 -51
  7. data/bin/launchy +2 -10
  8. data/lib/launchy.rb +96 -30
  9. data/lib/launchy/application.rb +55 -152
  10. data/lib/launchy/applications/browser.rb +68 -0
  11. data/lib/launchy/cli.rb +70 -0
  12. data/lib/launchy/descendant_tracker.rb +49 -0
  13. data/lib/launchy/detect.rb +10 -0
  14. data/lib/launchy/detect/host_os.rb +31 -0
  15. data/lib/launchy/detect/host_os_family.rb +71 -0
  16. data/lib/launchy/detect/nix_desktop_environment.rb +60 -0
  17. data/lib/launchy/detect/ruby_engine.rb +78 -0
  18. data/lib/launchy/detect/runner.rb +96 -0
  19. data/lib/launchy/error.rb +4 -0
  20. data/lib/launchy/os_family.rb +8 -0
  21. data/lib/launchy/version.rb +8 -7
  22. data/spec/application_spec.rb +26 -47
  23. data/spec/detect/host_os_family_spec.rb +40 -0
  24. data/spec/detect/host_os_spec.rb +19 -0
  25. data/spec/detect/nix_desktop_environment_spec.rb +13 -0
  26. data/spec/detect/ruby_engine_spec.rb +37 -0
  27. data/spec/launchy_spec.rb +29 -5
  28. data/spec/mock_scheme.rb +5 -0
  29. data/spec/spec_helper.rb +3 -3
  30. data/spec/{tattle-host-os.yml → tattle-host-os.yaml} +0 -0
  31. data/spec/version_spec.rb +4 -5
  32. metadata +67 -78
  33. data/gemspec.rb +0 -46
  34. data/lib/launchy/browser.rb +0 -98
  35. data/lib/launchy/command_line.rb +0 -48
  36. data/lib/launchy/paths.rb +0 -53
  37. data/spec/browser_spec.rb +0 -62
  38. data/spec/paths_spec.rb +0 -15
  39. data/tasks/announce.rake +0 -39
  40. data/tasks/config.rb +0 -107
  41. data/tasks/distribution.rake +0 -46
  42. data/tasks/documentation.rake +0 -32
  43. data/tasks/rspec.rake +0 -25
  44. data/tasks/rubyforge.rake +0 -52
  45. data/tasks/utils.rb +0 -80
@@ -0,0 +1,28 @@
1
+ # vim: ft=ruby
2
+
3
+ require 'autotest/growl'
4
+
5
+ Autotest.add_hook :initialize do |at|
6
+
7
+ at.libs = "lib:spec"
8
+ at.testlib = 'minitest/autorun'
9
+
10
+ at.add_exception 'coverage.info'
11
+ at.add_exception 'coverage'
12
+ at.add_exception '.git'
13
+
14
+ at.clear_mappings
15
+
16
+ at.add_mapping(%r|^spec/.*_spec\.rb$|) do |filename, _|
17
+ filename
18
+ end
19
+
20
+ at.add_mapping(%r|^lib/(.*)\.rb$|) do |_, match|
21
+ [ "test/#{match[1]}_spec.rb" ]
22
+ end
23
+
24
+ at.add_mapping(%r|^spec/spec_helper\.rb|) do
25
+ at.files_matching( %r|^spec/.*_spec\.rb| )
26
+ end
27
+ end
28
+
data/HISTORY CHANGED
@@ -1,5 +1,20 @@
1
1
  = Launchy Changlog
2
2
 
3
+ == Version 2.0.0 - 2011-07-16
4
+
5
+ * Almost a complete rewrite
6
+ * JRuby Support
7
+ * Organization is such that it will be easier to add additional applications
8
+ * Windows behavior possibly fixed, again
9
+
10
+ == Version 1.0.0 - 2011-03-17
11
+
12
+ * Add JRuby support (Stephen Judkins)
13
+ * Remove unused Paths module
14
+ * Switch to using bones
15
+ * Switch to use minitest
16
+ * NOTE, this version was never released.
17
+
3
18
  == Version 0.4.0 - 2011-01-27
4
19
 
5
20
  * Add support for file:/// schema (postmodern)
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  ISC LICENSE - http://opensource.org/licenses/isc-license.txt
2
2
 
3
- Copyright (c) 2007-2009 Jeremy Hinegardner
3
+ Copyright (c) 2007-2011 Jeremy Hinegardner
4
4
 
5
5
  Permission to use, copy, modify, and/or distribute this software for any
6
6
  purpose with or without fee is hereby granted, provided that the above
data/NOTES ADDED
@@ -0,0 +1 @@
1
+ * Allow for new tab/ new window for opening a browser
data/README CHANGED
@@ -1,7 +1,7 @@
1
1
  == launchy
2
2
 
3
- * Homepage[http://copiousfreetime.rubyforge.org/launchy/]
4
- * {Rubyforge Project}[http://rubyforge.org/projects/copiousfreetime]
3
+ * Homepage[http://www.copiousfreetime.org/projects/launchy/]
4
+ * {Github Project}[http://github.com/copiousfreetime/launchy]
5
5
  * email jeremy at hinegardner dot org
6
6
 
7
7
  == DESCRIPTION
@@ -11,7 +11,7 @@ fire and forget manner.
11
11
 
12
12
  There are application concepts (browser, email client, etc) that are
13
13
  common across all platforms, and they may be launched differently on
14
- each platform. Launchy is here to make a common approach to launching
14
+ each platform. Launchy is here to make a common approach to launching
15
15
  external application from within ruby programs.
16
16
 
17
17
  == FEATURES
@@ -26,17 +26,17 @@ From within your ruby code you can trust launchy to do the right thing:
26
26
 
27
27
  Or, if you want to launch the application yourself:
28
28
 
29
- Launchy::Browser.run("http://www.ruby-lang.org/")
29
+ Launchy::Browser.open("http://www.ruby-lang.org/")
30
30
 
31
31
  OR
32
32
 
33
- Launchy::Browser.new.visit("http://www.ruby-lang.org/")
33
+ Launchy::Browser.new.open("http://www.ruby-lang.org/")
34
34
 
35
35
  == ISC LICENSE
36
36
 
37
37
  http://opensource.org/licenses/isc-license.txt
38
38
 
39
- Copyright (c) 2007-2009 Jeremy Hinegardner
39
+ Copyright (c) 2007-2011 Jeremy Hinegardner
40
40
 
41
41
  Permission to use, copy, modify, and/or distribute this software for any
42
42
  purpose with or without fee is hereby granted, provided that the above
data/Rakefile CHANGED
@@ -3,60 +3,56 @@
3
3
  # All rights reserved. See LICENSE and/or COPYING for details.
4
4
  #++
5
5
 
6
- #-------------------------------------------------------------------------------
7
- # make sure our project's top level directory and the lib directory are added to
8
- # the ruby search path.
9
- #-------------------------------------------------------------------------------
10
- $: << File.expand_path(File.join(File.dirname(__FILE__),"lib"))
11
- $: << File.expand_path(File.dirname(__FILE__))
12
-
13
-
14
- #-------------------------------------------------------------------------------
15
- # load the global project configuration and add in the top level clean and
16
- # clobber tasks so that other tasks can utilize those constants if necessary
17
- # This loads up the defaults for the whole project configuration
18
- #-------------------------------------------------------------------------------
19
- require 'rubygems'
20
- require 'tasks/config.rb'
21
- require 'rake/clean'
22
-
23
- #-------------------------------------------------------------------------------
24
- # Main configuration for the project, these overwrite the items that are in
25
- # tasks/config.rb
26
- #-------------------------------------------------------------------------------
6
+ begin
7
+ require 'bones'
8
+ rescue LoadError
9
+ abort '### Please install the "bones" gem ###'
10
+ end
11
+
12
+ task :default => 'test:run'
13
+ task 'gem:release' => 'test:run'
14
+
15
+ $:.unshift( "lib" )
27
16
  require 'launchy/version'
28
- require 'launchy/paths'
29
17
 
30
- Configuration.for("project") {
18
+ Bones {
31
19
  name "launchy"
32
- version Launchy::VERSION
33
- author "Jeremy Hinegardner"
20
+ authors "Jeremy Hinegardner"
34
21
  email "jeremy@copiousfreetime.org"
35
- homepage "http://copiousfreetime.rubyforge.org/launchy/"
36
- }
22
+ url 'http://www.copiousfreetime.org/projects/launchy'
23
+ version Launchy::VERSION
37
24
 
38
- #-------------------------------------------------------------------------------
39
- # load up all the project tasks and setup the default task to be the
40
- # test:default task.
41
- #-------------------------------------------------------------------------------
42
- Configuration.for("packaging").files.tasks.each do |tasklib|
43
- import tasklib
44
- end
45
- task :default => 'test:default'
46
-
47
- #-------------------------------------------------------------------------------
48
- # Finalize the loading of all pending imports and update the top level clobber
49
- # task to depend on all possible sub-level tasks that have a name like
50
- # ':clobber' in other namespaces. This allows us to say:
51
- #
52
- # rake clobber
53
- #
54
- # and it will get everything.
55
- #-------------------------------------------------------------------------------
56
- Rake.application.load_imports
57
- Rake.application.tasks.each do |t|
58
- if t.name =~ /:clobber/ then
59
- task :clobber => [t.name]
60
- end
61
- end
25
+ ruby_opts %w[ -W0 -rubygems ]
26
+ readme_file 'README'
27
+ ignore_file '.gitignore'
28
+ history_file 'HISTORY'
62
29
 
30
+ rdoc.include << "README" << "HISTORY" << "LICENSE"
31
+
32
+ summary 'Launchy is helper class for launching cross-platform applications in a fire and forget manner.'
33
+ description <<_
34
+ Launchy is helper class for launching cross-platform applications in a
35
+ fire and forget manner.
36
+
37
+ There are application concepts (browser, email client, etc) that are
38
+ common across all platforms, and they may be launched differently on
39
+ each platform. Launchy is here to make a common approach to launching
40
+ external application from within ruby programs.
41
+ _
42
+
43
+ if RUBY_PLATFORM == "java" then
44
+ depend_on "spoon" , "~> 0.0.1"
45
+ gem.extras = { :platform => Gem::Platform.new( "java" ) }
46
+ end
47
+
48
+ depend_on "rake" , "~> 0.9.2", :development => true
49
+ depend_on "minitest", "~> 2.3.1", :development => true
50
+ depend_on 'bones' , "~> 3.7.0", :development => true
51
+
52
+ if defined?( RUBY_ENGINE ) and RUBY_ENGINE == "jruby" then
53
+ depend_on 'spoon' , "~> 0.0.1"
54
+ end
55
+
56
+ test.files = FileList["spec/**/*_spec.rb"]
57
+ test.opts << "-w -Ilib:spec"
58
+ }
@@ -1,12 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- begin
4
- require 'launchy'
5
- rescue LoadError
6
- path = File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
7
- raise if $:.include? path
8
- $: << path
9
- retry
10
- end
11
-
12
- Launchy.command_line.run(ARGV)
3
+ require 'launchy'
4
+ Launchy::Cli.new.run( ARGV, ENV )
@@ -1,53 +1,119 @@
1
+ require 'uri'
2
+
3
+ #
4
+ # Top level entry point into Launchy. Almost everyone will just use the single
5
+ # call:
6
+ #
7
+ # Launchy.open( uri, options = {} )
8
+ #
9
+ # The currently defined global options are:
10
+ #
11
+ # :debug Turn on debugging output
12
+ # :application Explicitly state what application class is going to be used
13
+ # :host_os Explicitly state what host operating system to pretend to be
14
+ # :ruby_engine Explicitly state what ruby engine to pretend to be under
15
+ #
16
+ # Other options may be used, and those will be passed directly to the
17
+ # application class
18
+ #
1
19
  module Launchy
2
- #
3
- # Utility method to require all files ending in .rb in the directory
4
- # with the same name as this file minus .rb
5
- #
6
- def self.require_all_libs_relative_to(fname)
7
- prepend = File.basename(fname,".rb")
8
- search_me = File.join(File.dirname(fname),prepend)
9
-
10
- Dir.entries(search_me).each do |rb|
11
- if File.extname(rb) == ".rb" then
12
- require "#{prepend}/#{File.basename(rb,".rb")}"
13
- end
14
- end
15
- end
16
20
 
17
21
  class << self
18
22
  #
19
23
  # Convenience method to launch an item
20
24
  #
21
- def open(*params)
25
+ def open(uri, options = {} )
22
26
  begin
23
- klass = Launchy::Application.find_application_class_for(*params)
24
- if klass then
25
- klass.run(*params)
27
+ extract_global_options( options )
28
+ uri = URI.parse( uri )
29
+ if app = Launchy::Application.for_scheme( uri ) then
30
+ app.new.open( uri, options )
26
31
  else
27
- msg = "Unable to launch #{params.join(' ')}"
32
+ msg = "Unable to launch #{uri} with options #{options.inspect}"
28
33
  Launchy.log "#{self.name} : #{msg}"
29
34
  $stderr.puts msg
30
35
  end
31
36
  rescue Exception => e
32
- msg = "Failure in opening #{params.join(' ')} : #{e}"
37
+ msg = "Failure in opening #{uri} with options #{options.inspect}: #{e}"
33
38
  Launchy.log "#{self.name} : #{msg}"
39
+ e.backtrace.each do |bt|
40
+ Launchy.log bt
41
+ end
34
42
  $stderr.puts msg
35
43
  end
36
44
  end
37
45
 
38
- # Setting the LAUNCHY_DEBUG environment variable to 'true' will spew
39
- # debug information to $stderr
40
- def log(msg)
41
- if ENV['LAUNCHY_DEBUG'] == 'true' then
42
- $stderr.puts "LAUNCHY_DEBUG: #{msg}"
43
- end
46
+ def reset_global_options
47
+ Launchy.debug = false
48
+ Launchy.application = nil
49
+ Launchy.host_os = nil
50
+ Launchy.ruby_engine = nil
51
+ Launchy.dry_run = false
52
+ end
53
+
54
+ def extract_global_options( options )
55
+ Launchy.debug = options.delete( :debug ) || ENV['LAUNCHY_DEBUG']
56
+ Launchy.application = options.delete( :application ) || ENV['LAUNCHY_APPLICATION']
57
+ Launchy.host_os = options.delete( :host_os ) || ENV['LAUNCHY_HOST_OS']
58
+ Launchy.ruby_engine = options.delete( :ruby_engine ) || ENV['LAUNCHY_RUBY_ENGINE']
59
+ Launchy.dry_run = options.delete( :dry_run )
60
+ end
61
+
62
+ def debug=( d )
63
+ @debug = (d == "true")
64
+ end
65
+
66
+ # we may do logging before a call to 'open', hence the need to check
67
+ # LAUNCHY_DEBUG here
68
+ def debug?
69
+ @debug || (ENV['LAUNCHY_DEBUG'] == 'true')
70
+ end
71
+
72
+ def application=( app )
73
+ @application = app
74
+ end
75
+
76
+ def application
77
+ @application || ENV['LAUNCHY_APPLICATION']
78
+ end
79
+
80
+ def host_os=( host_os )
81
+ @host_os = host_os
82
+ end
83
+
84
+ def host_os
85
+ @host_os || ENV['LAUNCHY_HOST_OS']
86
+ end
87
+
88
+ def ruby_engine=( ruby_engine )
89
+ @ruby_engine = ruby_engine
90
+ end
91
+
92
+ def ruby_engine
93
+ @ruby_engine || ENV['LAUNCHY_RUBY_ENGINE']
94
+ end
95
+
96
+ def dry_run=( dry_run )
97
+ @dry_run = dry_run
98
+ end
99
+
100
+ def dry_run?
101
+ @dry_run
102
+ end
103
+
104
+ def bug_report_message
105
+ "Please file a bug at https://github.com/copiousfreetime/launchy/issues/new"
44
106
  end
45
107
 
46
- # Create an instance of the commandline application of launchy
47
- def command_line
48
- Launchy::CommandLine.new
108
+ def log(msg)
109
+ $stderr.puts "LAUNCHY_DEBUG: #{msg}" if Launchy.debug?
49
110
  end
50
111
  end
51
112
  end
52
113
 
53
- Launchy.require_all_libs_relative_to(__FILE__)
114
+ require 'launchy/version'
115
+ require 'launchy/cli'
116
+ require 'launchy/descendant_tracker'
117
+ require 'launchy/error'
118
+ require 'launchy/application'
119
+ require 'launchy/detect'
@@ -1,178 +1,81 @@
1
- require 'rbconfig'
2
-
1
+ require 'set'
3
2
  module Launchy
3
+ #
4
+ # Application is the base class of all the application types that launchy may
5
+ # invoke. It essentially defines the public api of the launchy system.
6
+ #
7
+ # Every class that inherits from Application must define:
8
+ #
9
+ # 1. A constructor taking no parameters
10
+ # 2. An instance method 'open' taking a string or URI as the first parameter and a
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
4
14
  class Application
15
+ extend DescendantTracker
16
+
5
17
  class << self
6
- def known_os_families
7
- @known_os_families ||= [ :windows, :darwin, :nix, :cygwin, :testing ]
18
+ #
19
+ # The list of all the schemes all the applications know
20
+ #
21
+ def scheme_list
22
+ children.collect { |a| a.schemes }.flatten.sort
8
23
  end
9
24
 
10
- def inherited(sub_class)
11
- application_classes << sub_class
12
- end
13
- def application_classes
14
- @application_classes ||= []
25
+ #
26
+ # if this application handles the given scheme
27
+ #
28
+ def handles?( scheme )
29
+ schemes.include?( scheme )
15
30
  end
16
31
 
17
- def find_application_class_for(*args)
18
- Launchy.log "#{self.name} : finding application classes for [#{args.join(' ')}]"
19
- application_classes.find do |klass|
20
- Launchy.log "#{self.name} : Trying #{klass.name}"
21
- if klass.handle?(*args) then
22
- true
23
- else
24
- false
25
- end
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
26
39
  end
40
+
41
+ klass = find_child( :handles?, scheme )
42
+ return klass if klass
43
+
44
+ raise SchemeNotFoundError, "No application found to handle scheme '#{scheme}'. Known schemes: #{scheme_list.join(", ")}"
27
45
  end
28
46
 
29
- # find an executable in the available paths
30
- # mkrf did such a good job on this I had to borrow it.
31
- def find_executable(bin,*paths)
32
- paths = ENV['PATH'].split(File::PATH_SEPARATOR) if paths.empty?
47
+ #
48
+ # Find the given executable in the available paths
49
+ def find_executable( bin, *paths )
50
+ paths = ENV['PATH'].split( File::PATH_SEPARATOR ) if paths.empty?
33
51
  paths.each do |path|
34
- file = File.join(path,bin)
35
- if File.executable?(file) then
52
+ file = File.join( path, bin )
53
+ if File.executable?( file ) then
36
54
  Launchy.log "#{self.name} : found executable #{file}"
37
55
  return file
38
56
  end
39
57
  end
40
- Launchy.log "#{self.name} : Unable to find `#{bin}' in #{paths.join(', ')}"
58
+ Launchy.log "#{self.name} : Unable to find `#{bin}' in #{paths.join(", ")}"
41
59
  return nil
42
60
  end
43
-
44
- # return the current 'host_os' string from ruby's configuration
45
- def my_os
46
- if ENV['LAUNCHY_HOST_OS'] then
47
- Launchy.log "#{self.name} : Using LAUNCHY_HOST_OS override of '#{ENV['LAUNCHY_HOST_OS']}'"
48
- return ENV['LAUNCHY_HOST_OS']
49
- else
50
- ::Config::CONFIG['host_os']
51
- end
52
- end
53
-
54
- # detect what the current os is and return :windows, :darwin or :nix
55
- def my_os_family(test_os = my_os)
56
- case test_os
57
- when /mingw/i
58
- family = :windows
59
- when /mswin/i
60
- family = :windows
61
- when /windows/i
62
- family = :windows
63
- when /darwin/i
64
- family = :darwin
65
- when /mac os/i
66
- family = :darwin
67
- when /solaris/i
68
- family = :nix
69
- when /bsd/i
70
- family = :nix
71
- when /linux/i
72
- family = :nix
73
- when /aix/i
74
- family = :nix
75
- when /cygwin/i
76
- family = :cygwin
77
- when /testing/i
78
- family = :testing
79
- else
80
- $stderr.puts "Unknown OS familiy for '#{test_os}'. Please report this bug to <jeremy at hinegardner dot org>"
81
- family = :unknown
82
- end
83
- end
84
61
  end
85
62
 
86
-
87
- # Determine the appropriate desktop environment for *nix machine. Currently this is
88
- # linux centric. The detection is based upon the detection used by xdg-open from
89
- # http://portland.freedesktop.org/wiki/XdgUtils
90
- def nix_desktop_environment
91
- if not defined? @nix_desktop_environment then
92
- @nix_desktop_environment = :generic
93
- if ENV["KDE_FULL_SESSION"] || ENV["KDE_SESSION_UID"] then
94
- @nix_desktop_environment = :kde
95
- elsif ENV["GNOME_DESKTOP_SESSION_ID"] then
96
- @nix_desktop_environment = :gnome
97
- elsif find_executable("xprop") then
98
- if %x[ xprop -root _DT_SAVE_MODE | grep ' = \"xfce\"$' ].strip.size > 0 then
99
- @nix_desktop_environment = :xfce
100
- end
101
- end
102
- Launchy.log "#{self.class.name} : nix_desktop_environment => '#{@nix_desktop_environment}'"
103
- end
104
- return @nix_desktop_environment
63
+ attr_reader :host_os_family
64
+ attr_reader :ruby_engine
65
+ attr_reader :runner
66
+ def initialize
67
+ @host_os_family = Launchy::Detect::HostOsFamily.detect
68
+ @ruby_engine = Launchy::Detect::RubyEngine.detect
69
+ @runner = Launchy::Detect::Runner.detect
105
70
  end
106
71
 
107
- # find an executable in the available paths
108
- def find_executable(bin,*paths)
109
- Application.find_executable(bin,*paths)
72
+ def find_executable( bin, *paths )
73
+ Application.find_executable( bin, *paths )
110
74
  end
111
75
 
112
- # return the current 'host_os' string from ruby's configuration
113
- def my_os
114
- Application.my_os
115
- end
116
-
117
- # detect what the current os is and return :windows, :darwin, :nix, or :cygwin
118
- def my_os_family(test_os = my_os)
119
- Application.my_os_family(test_os)
120
- end
121
-
122
- # returns the list of command line application names for the current os. The list
123
- # returned should only contain appliations or commands that actually exist on the
124
- # system. The list members should have their full path to the executable.
125
- def app_list
126
- @app_list ||= self.send("#{my_os_family}_app_list")
127
- end
128
-
129
- # On darwin a good general default is the 'open' executable.
130
- def darwin_app_list
131
- Launchy.log "#{self.class.name} : Using 'open' application on darwin."
132
- [ find_executable('open') ]
133
- end
134
-
135
- # On windows a good general default is the 'start' Command Shell command
136
- def windows_app_list
137
- Launchy.log "#{self.class.name} : Using 'start' command on windows."
138
- %w[ start ]
139
- end
140
-
141
- # Cygwin uses the windows start but through an explicit execution of the cmd shell
142
- def cygwin_app_list
143
- Launchy.log "#{self.class.name} : Using 'cmd /C start' on windows."
144
- [ "cmd /C start" ]
145
- end
146
-
147
- # used only for running tests
148
- def testing_app_list
149
- []
150
- end
151
-
152
- # run the command
153
- def run(cmd,*args)
154
- Launchy.log "#{self.class.name} : Spawning on #{my_os_family} : #{cmd} #{args.inspect}"
155
-
156
- if my_os_family == :windows then
157
- # NOTE: the command is purposely omitted here because
158
- # When "cmd /c start filename" is
159
- # run, the shell interprets it as two commands:
160
- # (1) "start" opens a new terminal, and (2)
161
- # "filename" causes the file to be launched.
162
- system 'cmd', '/c', cmd, *args
163
- else
164
- # fork, and the child process should NOT run any exit handlers
165
- child_pid = fork do
166
- # NOTE: we pass a dummy argument *before*
167
- # the actual command to prevent sh
168
- # from silently consuming our actual
169
- # command and assigning it to $0!
170
- dummy = ''
171
- system 'sh', '-c', '"$@" >/dev/null 2>&1', dummy, cmd, *args
172
- exit!
173
- end
174
- Process.detach(child_pid)
175
- end
76
+ def run( cmd, *args )
77
+ runner.run( cmd, *args )
176
78
  end
177
79
  end
178
80
  end
81
+ require 'launchy/applications/browser'