wijet-launchy 2.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +111 -0
- data/LICENSE +16 -0
- data/NOTES +1 -0
- data/README +100 -0
- data/Rakefile +70 -0
- data/bin/launchy +4 -0
- data/lib/launchy.rb +115 -0
- data/lib/launchy/application.rb +62 -0
- data/lib/launchy/applications/browser.rb +79 -0
- data/lib/launchy/cli.rb +83 -0
- data/lib/launchy/deprecated.rb +52 -0
- data/lib/launchy/descendant_tracker.rb +49 -0
- data/lib/launchy/detect.rb +10 -0
- data/lib/launchy/detect/host_os.rb +31 -0
- data/lib/launchy/detect/host_os_family.rb +71 -0
- data/lib/launchy/detect/nix_desktop_environment.rb +60 -0
- data/lib/launchy/detect/ruby_engine.rb +78 -0
- data/lib/launchy/detect/runner.rb +111 -0
- data/lib/launchy/error.rb +4 -0
- data/lib/launchy/os_family.rb +8 -0
- data/lib/launchy/version.rb +18 -0
- data/spec/application_spec.rb +43 -0
- data/spec/applications/browser_spec.rb +54 -0
- data/spec/cli_spec.rb +75 -0
- data/spec/detect/host_os_family_spec.rb +40 -0
- data/spec/detect/host_os_spec.rb +19 -0
- data/spec/detect/nix_desktop_environment_spec.rb +33 -0
- data/spec/detect/ruby_engine_spec.rb +37 -0
- data/spec/detect/runner_spec.rb +98 -0
- data/spec/launchy_spec.rb +58 -0
- data/spec/mock_application.rb +9 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/tattle-host-os.yaml +427 -0
- data/spec/version_spec.rb +11 -0
- data/tasks/bundler.rake +13 -0
- data/tasks/contribute.rake +36 -0
- metadata +200 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
class Launchy::Application
|
2
|
+
#
|
3
|
+
# The class handling the browser application and all of its schemes
|
4
|
+
#
|
5
|
+
class Browser < Launchy::Application
|
6
|
+
def self.schemes
|
7
|
+
%w[ http https ftp file ]
|
8
|
+
end
|
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
|
+
|
15
|
+
def windows_app_list
|
16
|
+
[ 'start /b' ]
|
17
|
+
end
|
18
|
+
|
19
|
+
def cygwin_app_list
|
20
|
+
[ 'cmd /C start /b' ]
|
21
|
+
end
|
22
|
+
|
23
|
+
def darwin_app_list
|
24
|
+
[ find_executable( "open" ) ]
|
25
|
+
end
|
26
|
+
|
27
|
+
def nix_app_list
|
28
|
+
app_list = %w[ xdg-open ]
|
29
|
+
if nix_de = Launchy::Detect::NixDesktopEnvironment.detect then
|
30
|
+
app_list << nix_de.browser
|
31
|
+
app_list << nix_de.fallback_browsers
|
32
|
+
end
|
33
|
+
app_list.flatten!
|
34
|
+
app_list.delete_if { |b| b.nil? || (b.strip.size == 0) }
|
35
|
+
app_list.collect { |bin| find_executable( bin ) }.find_all { |x| not x.nil? }
|
36
|
+
end
|
37
|
+
|
38
|
+
# use a call back mechanism to get the right app_list that is decided by the
|
39
|
+
# host_os_family class.
|
40
|
+
def app_list
|
41
|
+
host_os_family.app_list( self )
|
42
|
+
end
|
43
|
+
|
44
|
+
def browser_env
|
45
|
+
return [] unless ENV['BROWSER']
|
46
|
+
browser_env = ENV['BROWSER'].split( File::PATH_SEPARATOR )
|
47
|
+
browser_env.flatten!
|
48
|
+
browser_env.delete_if { |b| b.nil? || (b.strip.size == 0) }
|
49
|
+
return browser_env
|
50
|
+
end
|
51
|
+
|
52
|
+
# Get the full commandline of what we are going to add the uri to
|
53
|
+
def browser_cmdline
|
54
|
+
possibilities = (browser_env + app_list).flatten
|
55
|
+
possibilities.each do |p|
|
56
|
+
Launchy.log "#{self.class.name} : possibility : #{p}"
|
57
|
+
end
|
58
|
+
browser = possibilities.shift
|
59
|
+
Launchy.log "#{self.class.name} : Using browser value '#{browser}'"
|
60
|
+
return browser
|
61
|
+
end
|
62
|
+
|
63
|
+
def cmd_and_args( uri, options = {} )
|
64
|
+
cmd = browser_cmdline
|
65
|
+
args = [ uri.to_s ]
|
66
|
+
if cmd =~ /%s/ then
|
67
|
+
cmd.gsub!( /%s/, args.shift )
|
68
|
+
end
|
69
|
+
return [cmd, args]
|
70
|
+
end
|
71
|
+
|
72
|
+
# final assembly of the command and do %s substitution
|
73
|
+
# http://www.catb.org/~esr/BROWSER/index.html
|
74
|
+
def open( uri, options = {} )
|
75
|
+
cmd, args = cmd_and_args( uri, options )
|
76
|
+
run( cmd, args )
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/launchy/cli.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Launchy
|
4
|
+
class Cli
|
5
|
+
|
6
|
+
attr_reader :options
|
7
|
+
def initialize
|
8
|
+
@options = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def parser
|
12
|
+
@parser ||= OptionParser.new do |op|
|
13
|
+
op.banner = "Usage: launchy [options] thing-to-launch"
|
14
|
+
|
15
|
+
op.separator ""
|
16
|
+
op.separator "Launch Options:"
|
17
|
+
|
18
|
+
op.on( "-a", "--application APPLICATION",
|
19
|
+
"Explicitly specify the application class to use in the launch") do |app|
|
20
|
+
@options[:application] = app
|
21
|
+
end
|
22
|
+
|
23
|
+
op.on( "-d", "--debug",
|
24
|
+
"Force debug. Output lots of information.") do |d|
|
25
|
+
@options[:debug] = 'true'
|
26
|
+
end
|
27
|
+
|
28
|
+
op.on( "-e", "--engine RUBY_ENGINE",
|
29
|
+
"Force launchy to behave as if it was on a particular ruby engine.") do |e|
|
30
|
+
@options[:ruby_engine] = e
|
31
|
+
end
|
32
|
+
|
33
|
+
op.on( "-n", "--dry-run", "Don't launchy, print the command to be executed on stdout" ) do |x|
|
34
|
+
@options[:dry_run] = true
|
35
|
+
end
|
36
|
+
|
37
|
+
op.on( "-o", "--host-os HOST_OS",
|
38
|
+
"Force launchy to behave as if it was on a particular host os.") do |os|
|
39
|
+
@options[:host_os] = os
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
op.separator ""
|
44
|
+
op.separator "Standard Options:"
|
45
|
+
|
46
|
+
op.on( "-h", "--help", "Print this message.") do |h|
|
47
|
+
$stdout.puts op.to_s
|
48
|
+
exit 0
|
49
|
+
end
|
50
|
+
|
51
|
+
op.on( "-v", "--version", "Output the version of Launchy") do |v|
|
52
|
+
$stdout.puts "Launchy version #{Launchy::VERSION}"
|
53
|
+
exit 0
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def parse( argv, env )
|
60
|
+
begin
|
61
|
+
parser.parse!( argv )
|
62
|
+
return true
|
63
|
+
rescue ::OptionParser::ParseError => pe
|
64
|
+
$stderr.puts "#{parser.program_name}: #{pe}"
|
65
|
+
$stderr.puts "Try `#{parser.program_name} --help for more information."
|
66
|
+
return false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def good_run( argv, env )
|
71
|
+
if parse( argv, env ) then
|
72
|
+
Launchy.open( argv.shift, options )
|
73
|
+
return true
|
74
|
+
else
|
75
|
+
return false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def run( argv = ARGV, env = ENV )
|
80
|
+
exit 1 unless good_run( argv, env )
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Launchy
|
2
|
+
#
|
3
|
+
# This class is deprecated and will be removed
|
4
|
+
#
|
5
|
+
class Browser
|
6
|
+
def self.run( *args )
|
7
|
+
Browser.new.visit( args[0] )
|
8
|
+
end
|
9
|
+
|
10
|
+
def visit( url )
|
11
|
+
_warn "You made a call to a deprecated Launchy API. This call should be changed to 'Launchy.open( uri )'"
|
12
|
+
report_caller_context( caller )
|
13
|
+
|
14
|
+
::Launchy.open( url )
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def find_caller_context( stack )
|
20
|
+
caller_file = stack.find do |line|
|
21
|
+
not line.index( __FILE__ )
|
22
|
+
end
|
23
|
+
if caller_file then
|
24
|
+
caller_fname, caller_line, _ = caller_file.split(":")
|
25
|
+
if File.readable?( caller_fname ) then
|
26
|
+
caller_lines = IO.readlines( caller_fname )
|
27
|
+
context = [ caller_file ]
|
28
|
+
context << caller_lines[(caller_line.to_i)-3, 5]
|
29
|
+
return context.flatten
|
30
|
+
end
|
31
|
+
end
|
32
|
+
return []
|
33
|
+
end
|
34
|
+
|
35
|
+
def report_caller_context( stack )
|
36
|
+
context = find_caller_context( stack )
|
37
|
+
if context.size > 0 then
|
38
|
+
_warn "I think I was able to find the location that needs to be fixed. Please go look at:"
|
39
|
+
_warn
|
40
|
+
context.each do |line|
|
41
|
+
_warn line.rstrip
|
42
|
+
end
|
43
|
+
_warn
|
44
|
+
_warn "If this is not the case, please file a bug. #{Launchy.bug_report_message}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def _warn( msg = "" )
|
49
|
+
warn "WARNING: #{msg}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Launchy
|
4
|
+
#
|
5
|
+
# Use by either
|
6
|
+
#
|
7
|
+
# class Foo
|
8
|
+
# extend DescendantTracker
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# or
|
12
|
+
#
|
13
|
+
# class Foo
|
14
|
+
# class << self
|
15
|
+
# include DescendantTracker
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# It will track all the classes that inherit from the extended class and keep
|
20
|
+
# them in a Set that is available via the 'children' method.
|
21
|
+
#
|
22
|
+
module DescendantTracker
|
23
|
+
def inherited( klass )
|
24
|
+
return unless klass.instance_of?( Class )
|
25
|
+
self.children << klass
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# The list of children that are registered
|
30
|
+
#
|
31
|
+
def children
|
32
|
+
unless defined? @children
|
33
|
+
@children = Set.new
|
34
|
+
end
|
35
|
+
return @children
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Find one of the child classes by calling the given method
|
40
|
+
# and passing all the rest of the parameters to that method in
|
41
|
+
# each child
|
42
|
+
def find_child( method, *args )
|
43
|
+
klass = children.find do |child|
|
44
|
+
Launchy.log "Checking if class #{child} is the one for #{method}(#{args.join(', ')})}"
|
45
|
+
child.send( method, *args )
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
module Launchy::Detect
|
4
|
+
class HostOs
|
5
|
+
|
6
|
+
attr_reader :host_os
|
7
|
+
alias to_s host_os
|
8
|
+
|
9
|
+
def initialize( host_os = nil )
|
10
|
+
@host_os = host_os
|
11
|
+
|
12
|
+
if not @host_os then
|
13
|
+
if @host_os = override_host_os then
|
14
|
+
Launchy.log "Using LAUNCHY_HOST_OS override value of '#{Launchy.host_os}'"
|
15
|
+
else
|
16
|
+
@host_os = default_host_os
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_host_os
|
22
|
+
::RbConfig::CONFIG['host_os']
|
23
|
+
end
|
24
|
+
|
25
|
+
def override_host_os
|
26
|
+
Launchy.host_os
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Launchy::Detect
|
2
|
+
# Detect the current host os family
|
3
|
+
#
|
4
|
+
# If the current host familiy cannot be detected then return
|
5
|
+
# HostOsFamily::Unknown
|
6
|
+
class HostOsFamily
|
7
|
+
class NotFoundError < Launchy::Error; end
|
8
|
+
extend ::Launchy::DescendantTracker
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def detect( host_os = HostOs.new )
|
13
|
+
found = find_child( :matches?, host_os )
|
14
|
+
return found.new( host_os ) if found
|
15
|
+
raise NotFoundError, "Unknown OS family for host os '#{host_os}'. #{Launchy.bug_report_message}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def matches?( host_os )
|
19
|
+
matching_regex.match( host_os.to_s )
|
20
|
+
end
|
21
|
+
|
22
|
+
def windows?() self == Windows; end
|
23
|
+
def darwin?() self == Darwin; end
|
24
|
+
def nix?() self == Nix; end
|
25
|
+
def cygwin?() self == Cygwin; end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
attr_reader :host_os
|
30
|
+
def initialize( host_os = HostOs.new )
|
31
|
+
@host_os = host_os
|
32
|
+
end
|
33
|
+
|
34
|
+
def windows?() self.class.windows?; end
|
35
|
+
def darwin?() self.class.darwin?; end
|
36
|
+
def nix?() self.class.nix?; end
|
37
|
+
def cygwin?() self.class.cygwin?; end
|
38
|
+
|
39
|
+
#---------------------------
|
40
|
+
# All known host os families
|
41
|
+
#---------------------------
|
42
|
+
#
|
43
|
+
class Windows < HostOsFamily
|
44
|
+
def self.matching_regex
|
45
|
+
/(mingw|mswin|windows)/i
|
46
|
+
end
|
47
|
+
def app_list( app ) app.windows_app_list; end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Darwin < HostOsFamily
|
51
|
+
def self.matching_regex
|
52
|
+
/(darwin|mac os)/i
|
53
|
+
end
|
54
|
+
def app_list( app ) app.darwin_app_list; end
|
55
|
+
end
|
56
|
+
|
57
|
+
class Nix < HostOsFamily
|
58
|
+
def self.matching_regex
|
59
|
+
/(linux|bsd|aix|solaris)/i
|
60
|
+
end
|
61
|
+
def app_list( app ) app.nix_app_list; end
|
62
|
+
end
|
63
|
+
|
64
|
+
class Cygwin < HostOsFamily
|
65
|
+
def self.matching_regex
|
66
|
+
/cygwin/i
|
67
|
+
end
|
68
|
+
def app_list( app ) app.cygwin_app_list; end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Launchy::Detect
|
2
|
+
#
|
3
|
+
# Detect the current desktop environment for *nix machines
|
4
|
+
# Currently this is Linux centric. The detection is based upon the detection
|
5
|
+
# used by xdg-open from http://portland.freedesktop.org/wiki/XdgUtils
|
6
|
+
class NixDesktopEnvironment
|
7
|
+
class NotFoundError < Launchy::Error; end
|
8
|
+
|
9
|
+
extend ::Launchy::DescendantTracker
|
10
|
+
|
11
|
+
# Detect the current *nix desktop environment
|
12
|
+
#
|
13
|
+
# If the current dekstop environment be detected, the return
|
14
|
+
# NixDekstopEnvironment::Unknown
|
15
|
+
def self.detect
|
16
|
+
found = find_child( :is_current_desktop_environment? )
|
17
|
+
Launchy.log("Current Desktop environment not flound. #{Launchy.bug_report_message}") unless found
|
18
|
+
return found
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.fallback_browsers
|
22
|
+
%w[ firefox seamonkey opera mozilla netscape galeon ]
|
23
|
+
end
|
24
|
+
|
25
|
+
#---------------------------------------
|
26
|
+
# The list of known desktop environments
|
27
|
+
#---------------------------------------
|
28
|
+
|
29
|
+
class Kde < NixDesktopEnvironment
|
30
|
+
def self.is_current_desktop_environment?
|
31
|
+
ENV['KDE_FULL_SESSION']
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.browser
|
35
|
+
'kfmclient'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Gnome < NixDesktopEnvironment
|
40
|
+
def self.is_current_desktop_environment?
|
41
|
+
ENV['GNOME_DESKTOP_SESSION_ID']
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.browser
|
45
|
+
'gnome-open'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Xfce < NixDesktopEnvironment
|
50
|
+
def self.is_current_desktop_environment?
|
51
|
+
%x[ xprop -root _DT_SAVE_MODE | grep ' = \"xfce\"$' ].strip.size > 0
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.browser
|
55
|
+
'exo-open'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Launchy::Detect
|
2
|
+
class RubyEngine
|
3
|
+
class NotFoundError < Launchy::Error; end
|
4
|
+
|
5
|
+
extend ::Launchy::DescendantTracker
|
6
|
+
|
7
|
+
# Detect the current ruby engine.
|
8
|
+
#
|
9
|
+
# If the current ruby engine cannot be detected, the return
|
10
|
+
# RubyEngine::Unknown
|
11
|
+
def self.detect( ruby_engine = RubyEngine.new )
|
12
|
+
found = find_child( :is_current_engine?, ruby_engine.to_s )
|
13
|
+
return found if found
|
14
|
+
raise NotFoundError, "#{ruby_engine_error_message( ruby_engine )} #{Launchy.bug_report_message}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.ruby_engine_error_message( ruby_engine )
|
18
|
+
msg = "Unkonwn RUBY_ENGINE "
|
19
|
+
if ruby_engine then
|
20
|
+
msg += " '#{ruby_engine}'."
|
21
|
+
elsif defined?( RUBY_ENGINE ) then
|
22
|
+
msg += " '#{RUBY_ENGINE}'."
|
23
|
+
else
|
24
|
+
msg = "RUBY_ENGINE not defined for #{RUBY_DESCRIPTION}."
|
25
|
+
end
|
26
|
+
return msg
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.is_current_engine?( ruby_engine )
|
30
|
+
return ruby_engine == self.engine_name
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.mri?() self == Mri; end
|
34
|
+
def self.jruby?() self == Jruby; end
|
35
|
+
def self.rbx?() self == Rbx; end
|
36
|
+
def self.macruby?() self == MacRuby; end
|
37
|
+
|
38
|
+
attr_reader :ruby_engine
|
39
|
+
alias to_s ruby_engine
|
40
|
+
def initialize( ruby_engine = Launchy.ruby_engine )
|
41
|
+
if ruby_engine then
|
42
|
+
@ruby_engine = ruby_engine
|
43
|
+
else
|
44
|
+
@ruby_engine = defined?( RUBY_ENGINE ) ? RUBY_ENGINE : "ruby"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
#-------------------------------
|
50
|
+
# The list of known ruby engines
|
51
|
+
#-------------------------------
|
52
|
+
|
53
|
+
#
|
54
|
+
# This is the ruby engine if the RUBY_ENGINE constant is not defined
|
55
|
+
class Mri < RubyEngine
|
56
|
+
def self.engine_name() "ruby"; end
|
57
|
+
def self.is_current_engine?( ruby_engine )
|
58
|
+
if ruby_engine then
|
59
|
+
super( ruby_engine )
|
60
|
+
else
|
61
|
+
return true if not Launchy.ruby_engine and not defined?( RUBY_ENGINE )
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Jruby < RubyEngine
|
67
|
+
def self.engine_name() "jruby"; end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Rbx < RubyEngine
|
71
|
+
def self.engine_name() "rbx"; end
|
72
|
+
end
|
73
|
+
|
74
|
+
class MacRuby < RubyEngine
|
75
|
+
def self.engine_name() "macruby"; end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|