Permalink
Browse files

Start of a major refactoring

  • Loading branch information...
1 parent 741c039 commit cb31804c06407e1059baf2449b5f6ee8aed542bd @copiousfreetime committed May 16, 2011
View
@@ -0,0 +1,28 @@
+# vim: ft=ruby
+
+require 'autotest/growl'
+
+Autotest.add_hook :initialize do |at|
+
+ at.libs = "lib:spec"
+ at.testlib = 'minitest/autorun'
+
+ at.add_exception 'coverage.info'
+ at.add_exception 'coverage'
+ at.add_exception '.git'
+
+ at.clear_mappings
+
+ at.add_mapping(%r|^spec/.*_spec\.rb$|) do |filename, _|
+ filename
+ end
+
+ at.add_mapping(%r|^lib/(.*)\.rb$|) do |_, match|
+ [ "test/#{match[1]}_spec.rb" ]
+ end
+
+ at.add_mapping(%r|^spec/spec_helper\.rb|) do
+ at.files_matching( %r|^spec/.*_spec\.rb| )
+ end
+end
+
View
6 README
@@ -11,7 +11,7 @@ fire and forget manner.
There are application concepts (browser, email client, etc) that are
common across all platforms, and they may be launched differently on
-each platform. Launchy is here to make a common approach to launching
+each platform. Launchy is here to make a common approach to launching
external application from within ruby programs.
== FEATURES
@@ -26,11 +26,11 @@ From within your ruby code you can trust launchy to do the right thing:
Or, if you want to launch the application yourself:
- Launchy::Browser.run("http://www.ruby-lang.org/")
+ Launchy::Browser.open("http://www.ruby-lang.org/")
OR
- Launchy::Browser.new.visit("http://www.ruby-lang.org/")
+ Launchy::Browser.new.open("http://www.ruby-lang.org/")
== ISC LICENSE
View
@@ -50,4 +50,5 @@ _
depend_on 'bones' , "~> 3.6.5", :development => true
test.files = FileList["spec/**/*_spec.rb"]
+ test.opts << "-Ilib:spec"
}
View
@@ -1,12 +1,4 @@
#!/usr/bin/env ruby
-begin
- require 'launchy'
-rescue LoadError
- path = File.expand_path( "../lib", File.dirname(__FILE__) )
- raise if $:.include? path
- $:.unshift( path )
- retry
-end
-
-Launchy.command_line.run(ARGV)
+require 'launchy'
+Launchy::Cli.new.run( ARGV, ENV )
View
@@ -1,15 +1,17 @@
+
module Launchy
+
class << self
#
# Convenience method to launch an item
#
- def open(*params)
+ def open(uri, options = {} )
begin
- klass = Launchy::Application.find_application_class_for(*params)
- if klass then
- klass.run(*params)
+ uri = URI.parse( uri )
+ if app = Launchy::Application.for_scheme( uri ) then
+ app.new.open( uri, options )
else
- msg = "Unable to launch #{params.join(' ')}"
+ msg = "Unable to launch #{uri} with options #{options.inspect}"
Launchy.log "#{self.name} : #{msg}"
$stderr.puts msg
end
@@ -20,24 +22,18 @@ def open(*params)
end
end
+ def debug?
+ ENV['LAUNCHY_DEBUG'] == 'true'
+ end
+
# Setting the LAUNCHY_DEBUG environment variable to 'true' will spew
# debug information to $stderr
def log(msg)
- if ENV['LAUNCHY_DEBUG'] == 'true' then
- $stderr.puts "LAUNCHY_DEBUG: #{msg}"
- end
- end
-
- # Create an instance of the commandline application of launchy
- def command_line
- Launchy::CommandLine.new
+ $stderr.puts "LAUNCHY_DEBUG: #{msg}" if debug?
end
end
end
-require 'launchy/application'
-require 'launchy/browser'
-require 'launchy/command_line'
require 'launchy/version'
-
-require 'spoon' if Launchy::Application.is_jruby?
+require 'launchy/error'
+require 'launchy/application'
View
@@ -1,192 +1,65 @@
-require 'rbconfig'
-
+require 'set'
module Launchy
+ #
+ # Application is the base class of all the application types that launchy may
+ # invoke. It essentially defines the public api of the launchy system.
+ #
+ # Every class that inherits from Application must define:
+ #
+ # 1. A constructor taking no parameters
+ # 2. An instance method 'open' taking a string or URI as the first parameter and a
+ # hash as the second
+ # 3. A class method 'schemes' that returns an array of Strings containing the
+ # schemes that the Application will handle
class Application
class << self
- def known_os_families
- @known_os_families ||= [ :windows, :darwin, :nix, :cygwin, :testing ]
+ #
+ # track child classes as they are created
+ #
+ def inherited( klass )
+ return unless klass.instance_of?( Class )
+ self.application_list << klass
end
- def inherited(sub_class)
- application_classes << sub_class
- end
- def application_classes
- @application_classes ||= []
- end
-
- def find_application_class_for(*args)
- Launchy.log "#{self.name} : finding application classes for [#{args.join(' ')}]"
- application_classes.find do |klass|
- Launchy.log "#{self.name} : Trying #{klass.name}"
- if klass.handle?(*args) then
- true
- else
- false
- end
+ #
+ # The list of applications that are registered
+ #
+ def application_list
+ unless defined? @application_list
+ @application_list = Set.new
end
+ return @application_list
end
- # find an executable in the available paths
- # mkrf did such a good job on this I had to borrow it.
- def find_executable(bin,*paths)
- paths = ENV['PATH'].split(File::PATH_SEPARATOR) if paths.empty?
- paths.each do |path|
- file = File.join(path,bin)
- if File.executable?(file) then
- Launchy.log "#{self.name} : found executable #{file}"
- return file
- end
- end
- Launchy.log "#{self.name} : Unable to find `#{bin}' in #{paths.join(', ')}"
- return nil
+ #
+ # The list of all the schems all the applications now
+ #
+ def scheme_list
+ application_list.collect { |a| a.schemes }.flatten.sort
end
- # return the current 'host_os' string from ruby's configuration
- def my_os
- if ENV['LAUNCHY_HOST_OS'] then
- Launchy.log "#{self.name} : Using LAUNCHY_HOST_OS override of '#{ENV['LAUNCHY_HOST_OS']}'"
- return ENV['LAUNCHY_HOST_OS']
- else
- ::Config::CONFIG['host_os']
- end
+ #
+ # if this application handles the given scheme
+ #
+ def handles?( scheme )
+ schemes.include?( scheme )
end
- # detect what the current os is and return :windows, :darwin or :nix
- def my_os_family(test_os = my_os)
- case test_os
- when /mingw/i
- family = :windows
- when /mswin/i
- family = :windows
- when /windows/i
- family = :windows
- when /darwin/i
- family = :darwin
- when /mac os/i
- family = :darwin
- when /solaris/i
- family = :nix
- when /bsd/i
- family = :nix
- when /linux/i
- family = :nix
- when /aix/i
- family = :nix
- when /cygwin/i
- family = :cygwin
- when /testing/i
- family = :testing
- else
- $stderr.puts "Unknown OS familiy for '#{test_os}'. Please report this bug to <jeremy at hinegardner dot org>"
- family = :unknown
+ #
+ # Find the application that handles the given scheme. May take either a
+ # String or something that responds_to?( :scheme )
+ #
+ def for_scheme( scheme )
+ if scheme.respond_to?( :scheme ) then
+ scheme = scheme.scheme
end
- end
-
- def is_jruby?
- defined?(RUBY_PLATFORM) && ( RUBY_PLATFORM == "java" )
- end
- end
+ klass = application_list.find { |klass| klass.handles?( scheme ) }
- # Determine the appropriate desktop environment for *nix machine. Currently this is
- # linux centric. The detection is based upon the detection used by xdg-open from
- # http://portland.freedesktop.org/wiki/XdgUtils
- def nix_desktop_environment
- if not defined? @nix_desktop_environment then
- @nix_desktop_environment = :generic
- if ENV["KDE_FULL_SESSION"] || ENV["KDE_SESSION_UID"] then
- @nix_desktop_environment = :kde
- elsif ENV["GNOME_DESKTOP_SESSION_ID"] then
- @nix_desktop_environment = :gnome
- elsif find_executable("xprop") then
- if %x[ xprop -root _DT_SAVE_MODE | grep ' = \"xfce\"$' ].strip.size > 0 then
- @nix_desktop_environment = :xfce
- end
- end
- Launchy.log "#{self.class.name} : nix_desktop_environment => '#{@nix_desktop_environment}'"
+ return klass if klass
+ raise SchemeNotFoundError, "No application found to handle scheme '#{scheme}'. Known schemes: #{scheme_list.join(", ")}"
end
- return @nix_desktop_environment
end
- # find an executable in the available paths
- def find_executable(bin,*paths)
- Application.find_executable(bin,*paths)
- end
-
- # return the current 'host_os' string from ruby's configuration
- def my_os
- Application.my_os
- end
-
- # detect what the current os is and return :windows, :darwin, :nix, or :cygwin
- def my_os_family(test_os = my_os)
- Application.my_os_family(test_os)
- end
-
- def is_jruby?
- Application.is_jruby?
- end
-
- # returns the list of command line application names for the current os. The list
- # returned should only contain appliations or commands that actually exist on the
- # system. The list members should have their full path to the executable.
- def app_list
- @app_list ||= self.send("#{my_os_family}_app_list")
- end
-
- # On darwin a good general default is the 'open' executable.
- def darwin_app_list
- Launchy.log "#{self.class.name} : Using 'open' application on darwin."
- [ find_executable('open') ]
- end
-
- # On windows a good general default is the 'start' Command Shell command
- def windows_app_list
- Launchy.log "#{self.class.name} : Using 'start' command on windows."
- %w[ start ]
- end
-
- # Cygwin uses the windows start but through an explicit execution of the cmd shell
- def cygwin_app_list
- Launchy.log "#{self.class.name} : Using 'cmd /C start' on windows."
- [ "cmd /C start" ]
- end
-
- # used only for running tests
- def testing_app_list
- []
- end
-
- def shell_commands(cmd, args)
- # NOTE: we pass a dummy argument *before*
- # the actual command to prevent sh
- # from silently consuming our actual
- # command and assigning it to $0!
- dummy = ''
- ['sh', '-c', '"$@" >/dev/null 2>&1', dummy, cmd, *args]
- end
-
- # run the command
- def run(cmd,*args)
- Launchy.log "#{self.class.name} : Spawning on #{my_os_family} : #{cmd} #{args.inspect}"
-
- if my_os_family == :windows then
- # NOTE: the command is purposely omitted here because
- # When "cmd /c start filename" is
- # run, the shell interprets it as two commands:
- # (1) "start" opens a new terminal, and (2)
- # "filename" causes the file to be launched.
- system 'cmd', '/c', cmd, *args
- elsif is_jruby?
- Spoon.spawnp *shell_commands(cmd, args)
- else
- # fork, and the child process should NOT run any exit handlers
- child_pid = fork do
- system *shell_commands(cmd, args)
- exit!
- end
- Process.detach(child_pid)
- end
- end
end
end
Oops, something went wrong.

0 comments on commit cb31804

Please sign in to comment.