utility_belt 1.0.6 → 1.1.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/bin/amazon +4 -5
  2. data/bin/google +5 -16
  3. data/bin/pastie +6 -0
  4. data/lib/utility_belt.rb +13 -30
  5. data/lib/utility_belt/amazon_upload_shortcut.rb +25 -0
  6. data/lib/utility_belt/clipboard.rb +52 -0
  7. data/lib/{command_history.rb → utility_belt/command_history.rb} +20 -5
  8. data/lib/utility_belt/convertable_to_file.rb +34 -0
  9. data/lib/utility_belt/equipper.rb +72 -0
  10. data/lib/utility_belt/google.rb +33 -0
  11. data/lib/utility_belt/hash_math.rb +10 -0
  12. data/lib/utility_belt/interactive_editor.rb +78 -0
  13. data/lib/{irb_options.rb → utility_belt/irb_options.rb} +0 -0
  14. data/lib/{irb_verbosity_control.rb → utility_belt/irb_verbosity_control.rb} +0 -0
  15. data/lib/{is_an.rb → utility_belt/is_an.rb} +0 -0
  16. data/lib/{language_greps.rb → utility_belt/language_greps.rb} +0 -0
  17. data/lib/{not.rb → utility_belt/not.rb} +0 -0
  18. data/lib/utility_belt/pastie.rb +33 -0
  19. data/lib/utility_belt/pipe.rb +24 -0
  20. data/lib/utility_belt/prompt.rb +1 -0
  21. data/lib/{rails_finder_shortcut.rb → utility_belt/rails_finder_shortcut.rb} +0 -0
  22. data/lib/{rails_verbosity_control.rb → utility_belt/rails_verbosity_control.rb} +0 -0
  23. data/lib/{string_to_proc.rb → utility_belt/string_to_proc.rb} +0 -0
  24. data/lib/{symbol_to_proc.rb → utility_belt/symbol_to_proc.rb} +0 -0
  25. data/lib/{themes.rb → utility_belt/wirble.rb} +4 -0
  26. data/lib/{with.rb → utility_belt/with.rb} +0 -0
  27. data/spec/convertable_to_file_spec.rb +31 -0
  28. data/spec/equipper_spec.rb +70 -0
  29. data/spec/hash_math_spec.rb +32 -0
  30. data/spec/interactive_editor_spec.rb +146 -0
  31. data/{test → spec}/language_greps_spec.rb +3 -2
  32. data/spec/pastie_spec.rb +92 -0
  33. data/spec/pipe_spec.rb +30 -0
  34. data/spec/spec_helper.rb +8 -0
  35. data/{test → spec}/string_to_proc_spec.rb +2 -1
  36. data/{test → spec}/utility_belt_spec.rb +1 -0
  37. data/utility_belt.gemspec +5 -5
  38. metadata +42 -29
  39. data/Rakefile +0 -20
  40. data/lib/amazon_upload_shortcut.rb +0 -18
  41. data/lib/hash_math.rb +0 -13
  42. data/lib/interactive_editor.rb +0 -42
  43. data/lib/mac_clipboard.rb +0 -15
  44. data/lib/pastie.rb +0 -15
  45. data/test/hash_math_spec.rb +0 -16
data/bin/amazon CHANGED
@@ -8,11 +8,10 @@ filenames = option_parser.parse(ARGV)
8
8
  abort "Usage: amazon -b bucket_name file_name" unless @bucket && filenames
9
9
 
10
10
  # require files, populate hash
11
- UTILITY_BELT_IRB_STARTUP_PROCS = {}
12
- utility_belt_lib = File.dirname(__FILE__) + '/../lib'
13
- require "#{utility_belt_lib}/mac_clipboard"
14
- require "#{utility_belt_lib}/amazon_upload_shortcut"
15
- UTILITY_BELT_IRB_STARTUP_PROCS[:define_s3_convenience_methods].call
11
+ require 'utility_belt'
12
+ UtilityBelt.equip(:amazon_upload_shortcut)
13
+ UtilityBelt.equip(:clipboard)
14
+ include UtilityBelt::AmazonUploadShortcut
16
15
 
17
16
  # baddabing, baddaboom
18
17
  filenames.each {|filename| puts aws_upload(@bucket, filename)}
data/bin/google CHANGED
@@ -1,18 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
- %w{rubygems platform cgi}.each {|library| require library}
2
+ %w{rubygems platform net/http utility_belt}.each {|library| require library}
3
3
 
4
- if :macosx != Platform::IMPL
5
- abort "Utility Belt's command-line Google shortcut only works on OS X. Sorry."
6
- else
7
- require "#{File.dirname(__FILE__) + '/../lib'}/mac_clipboard"
8
- search_term = ARGV[0] || MacClipboard.read
9
- if search_term.empty?
10
- puts "Usage: google search_term_without_spaces"
11
- puts " google 'search term with spaces'"
12
- puts " google"
13
- puts " (if invoking without command-line args, must have text in clipboard)"
14
- puts " (if you're seeing this there's a good chance you copied an image or something)"
15
- exit
16
- end
17
- system("open http://google.com/search?q=#{CGI.escape(search_term)}")
18
- end
4
+ UtilityBelt.equip(:google)
5
+ include UtilityBelt::Google
6
+
7
+ google(ARGV[0])
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ %w{rubygems utility_belt}.each {|library| require library}
3
+ UtilityBelt.equip(:pastie)
4
+ include UtilityBelt::Pastie
5
+
6
+ pastie(ARGV[0])
@@ -3,37 +3,20 @@
3
3
  # Check that file for usage information, authorship, copyright, and extensive details. You can also find a
4
4
  # nice, HTMLified version of the README content at http://utilitybelt.rubyforge.org.
5
5
 
6
- UTILITY_BELT_IRB_STARTUP_PROCS = {}
6
+ UTILITY_BELT_IRB_STARTUP_PROCS = {} unless Object.const_defined? :UTILITY_BELT_IRB_STARTUP_PROCS
7
7
 
8
- %w{rubygems
9
- platform
10
- wirble
11
- net/http
12
- tempfile}.each {|library| require library}
13
- %w{init colorize}.each {|message| Wirble.send(message)}
14
- %w{mac_clipboard
15
- is_an
16
- pastie
17
- themes
18
- irb_verbosity_control
19
- rails_verbosity_control
20
- command_history
21
- not
22
- language_greps
23
- rails_finder_shortcut
24
- amazon_upload_shortcut
25
- irb_options
26
- interactive_editor
27
- string_to_proc
28
- symbol_to_proc
29
- hash_math
30
- with}.each {|internal_library| require internal_library}
8
+ %w{rubygems utility_belt/equipper}.each {|internal_library| require internal_library}
31
9
 
32
- # default: dark background
33
- UtilityBelt::Themes.background(:dark)
10
+ if Object.const_defined? :IRB
34
11
 
35
- # Called when the irb session is ready, after any external libraries have been loaded. I can't
36
- # remember why I did this. it might be a cargo cult thing.
37
- IRB.conf[:IRB_RC] = lambda do
38
- UTILITY_BELT_IRB_STARTUP_PROCS.each {|symbol, proc| proc.call}
12
+ # Called when the irb session is ready, after any external libraries have been loaded. This
13
+ # allows the user to specify which gadgets in the utility belt to equip. (Kind of pushing the
14
+ # metaphor, but hey, what the hell.)
15
+ IRB.conf[:IRB_RC] = lambda do
16
+ UtilityBelt.equip(:defaults) unless UtilityBelt.equipped?
17
+ UTILITY_BELT_IRB_STARTUP_PROCS.each {|symbol, proc| proc.call}
18
+ end
19
+
20
+ # default: dark background
21
+ UtilityBelt::Themes.background(:dark) if defined? UtilityBelt::Themes
39
22
  end
@@ -0,0 +1,25 @@
1
+ # S3 (http://amazon.rubyforge.org/)
2
+ %w{aws/s3 cgi platform}.each {|lib| require lib}
3
+
4
+ module UtilityBelt
5
+ module AmazonUploadShortcut
6
+ def aws_upload(bucket,filename)
7
+ AWS::S3::Base.establish_connection!(:access_key_id => ENV['AMAZON_ACCESS_KEY_ID'],
8
+ :secret_access_key => ENV['AMAZON_SECRET_ACCESS_KEY'])
9
+ AWS::S3::S3Object.store(filename, open(filename), bucket, :access => :public_read)
10
+ url = "http://s3.amazonaws.com/#{bucket}/#{filename}".gsub(/ /, "%20")
11
+ Clipboard.write(url) if Clipboard.available?
12
+ url
13
+ end
14
+ end
15
+ end
16
+
17
+ class Object
18
+ include UtilityBelt::AmazonUploadShortcut
19
+ end if Object.const_defined? :IRB
20
+
21
+ # a quick note: the "google" command uses CGI.escape, but the URLs produced by CGI.escape
22
+ # don't seem to succeed here, in practice. this may differ by OS and/or browser. Let me
23
+ # know if you see something weird -- the Utility Belt mailing list is here:
24
+ #
25
+ # http://rubyforge.org/mailman/listinfo/utilitybelt-tinkering
@@ -0,0 +1,52 @@
1
+ # original clipboard code: http://project.ioni.st/post/1334#snippet_1334
2
+ # turned it into a class to make it flexxy:
3
+ # http://gilesbowkett.blogspot.com/2007/09/improved-auto-pastie-irb-code.html
4
+ # Extended to handle windows and linux as well
5
+ require 'platform'
6
+
7
+ module UtilityBelt
8
+ class Clipboard
9
+
10
+ def self.available?
11
+ @@implemented || false
12
+ end
13
+
14
+ case Platform::IMPL
15
+ when :macosx
16
+
17
+ def self.read
18
+ IO.popen('pbpaste') {|clipboard| clipboard.read}
19
+ end
20
+
21
+ def self.write(stuff)
22
+ IO.popen('pbcopy', 'w+') {|clipboard| clipboard.write(stuff)}
23
+ end
24
+ @@implemented = true
25
+
26
+ when :mswin
27
+
28
+ begin
29
+ # Try loading the win32-clipboard gem
30
+ require 'win32/clipboard'
31
+
32
+ def self.read
33
+ Win32::Clipboard.data
34
+ end
35
+
36
+ def self.write(stuff)
37
+ Win32::Clipboard.set_data(stuff)
38
+ end
39
+ @@implemented = true
40
+
41
+ rescue LoadError
42
+ raise "You need the win32-clipboard gem for clipboard functionality!"
43
+ end
44
+
45
+ else
46
+ raise "No suitable clipboard implementation for your platform found!"
47
+ end
48
+
49
+ end
50
+ end
51
+
52
+ Clipboard = UtilityBelt::Clipboard if Object.const_defined? :IRB
@@ -23,6 +23,8 @@
23
23
  # $Id: history.rb 50 2007-07-30 18:55:09Z ben $
24
24
  #
25
25
 
26
+ require 'tempfile'
27
+
26
28
  class Object
27
29
  def history(how_many = 50)
28
30
  history_size = Readline::HISTORY.size
@@ -54,15 +56,28 @@ class Object
54
56
  end
55
57
  file.close
56
58
  end
59
+
60
+ # hack to handle JRuby bug
61
+ def handling_jruby_bug(&block)
62
+ if RUBY_PLATFORM =~ /java/
63
+ puts "JRuby IRB has a bug which prevents successful IRB vi interoperation."
64
+ puts "The JRuby team is aware of this and working on it."
65
+ puts "(http://jira.codehaus.org/browse/JRUBY-2049)"
66
+ else
67
+ yield
68
+ end
69
+ end
57
70
 
58
71
  # TODO: history_write should go to a file, or the clipboard, or a file which opens in an application
59
72
  def history_to_vi
60
- file = Tempfile.new("irb_tempfile")
61
- get_lines(0..(Readline::HISTORY.size - 1)).each do |line|
62
- file << "#{line}\n"
73
+ handling_jruby_bug do
74
+ file = Tempfile.new("irb_tempfile")
75
+ get_lines(0..(Readline::HISTORY.size - 1)).each do |line|
76
+ file << "#{line}\n"
77
+ end
78
+ file.close
79
+ system("vim #{file.path}")
63
80
  end
64
- file.close
65
- system("vim #{file.path}")
66
81
  end
67
82
  alias :hvi :history_to_vi
68
83
 
@@ -0,0 +1,34 @@
1
+ require 'tempfile'
2
+
3
+ # This module adds a method, #to_file, which dumps the contents of self into a
4
+ # temp file and then returns the path of that file. This is particularly useful
5
+ # when calling out to shell commands which expect their input in the form of
6
+ # files.
7
+ #
8
+ # Example: use UNIX 'diff' to compare two objects:
9
+ #
10
+ # >> a = ["foo", "bar", "baz"].join("\n")
11
+ # => "foo\nbar\nbaz"
12
+ # >> b = ["foo", "buz", "baz"].join("\n")
13
+ # => "foo\nbuz\nbaz"
14
+ # >> puts `diff #{a.to_file} #{b.to_file}`
15
+ # 2c2
16
+ # < bar
17
+ # ---
18
+ # > buz
19
+ # => nil
20
+ #
21
+ module ConvertableToFile
22
+ def to_file
23
+ path = nil
24
+ Tempfile.open(object_id.to_s) do |tempfile|
25
+ tempfile << self
26
+ path = tempfile.path
27
+ end
28
+ path
29
+ end
30
+ end
31
+
32
+ class Object
33
+ include ConvertableToFile
34
+ end
@@ -0,0 +1,72 @@
1
+ # Allow to select which gadgets to equip
2
+ #
3
+ # Author: Markus Prinz <markus.prinz@qsig.org>
4
+
5
+ module UtilityBelt
6
+ class << self
7
+ def equip(*args)
8
+ Equipper.equip(*args)
9
+ end
10
+ def equipped?
11
+ Equipper.equipped?
12
+ end
13
+ end
14
+ module Equipper
15
+ GADGETS = Dir[File.join(File.dirname(__FILE__), '*.rb')].map{|file| File.basename(file)[0..-4]}.reject{|gadget| "equipper" == gadget }
16
+
17
+ DEFAULTS = %w{wirble
18
+ hash_math
19
+ command_history
20
+ interactive_editor
21
+ irb_options
22
+ irb_verbosity_control}
23
+
24
+ @equipped = false
25
+
26
+ class << self
27
+ def equip(*args)
28
+ return if args.empty?
29
+
30
+ gadgets_to_equip = []
31
+
32
+ # Special case using :all or :none
33
+ if args[0].is_a?(Symbol) && [:all, :none, :defaults].include?(args[0])
34
+ what = args[0]
35
+
36
+ unless args[1].nil?
37
+ exceptions = args[1].has_key?(:except) ? args[1][:except] : []
38
+
39
+ # Handle special case where we get a string or a symbol instead of an array
40
+ exceptions = exceptions.to_s.to_a unless exceptions.is_a?( Array )
41
+ else
42
+ exceptions = []
43
+ end
44
+
45
+ case what
46
+ when :all
47
+ gadgets_to_equip.push(*(GADGETS - exceptions))
48
+ when :none
49
+ gadgets_to_equip.push(*exceptions)
50
+ when :defaults
51
+ gadgets_to_equip.push(*DEFAULTS)
52
+ end
53
+ # otherwise, args is a list of gadgets to equip
54
+ else
55
+ args.each do |arg|
56
+ gadget = arg.to_s
57
+
58
+ # Silently ignore unkown gadgets
59
+ gadgets_to_equip << gadget if GADGETS.include? gadget
60
+ end
61
+ end
62
+
63
+ gadgets_to_equip.each{|gadget| require "utility_belt/#{gadget}" }
64
+
65
+ @equipped ||= true
66
+ end
67
+ def equipped?
68
+ @equipped
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ %w{rubygems platform cgi}.each {|library| require library}
3
+
4
+ UtilityBelt.equip(:clipboard)
5
+
6
+ module UtilityBelt
7
+ module Google
8
+ def google(search_term = nil)
9
+ search_term ||= Clipboard.read if Clipboard.available?
10
+ if search_term.empty?
11
+ puts "Usage: google search_term_without_spaces (Unix command line only)"
12
+ puts " google 'search term with spaces' (Unix or IRB)"
13
+ puts " google (Unix or IRB)"
14
+ puts " (if invoking without args, must have text in clipboard)"
15
+ else
16
+ url = "http://google.com/search?q=#{CGI.escape(search_term)}"
17
+ case Platform::IMPL
18
+ when :macosx
19
+ Kernel.system("open #{url}")
20
+ when :windows
21
+ Kernel.system("start #{url}")
22
+ #when :linux
23
+ else
24
+ puts "Sorry, don't know how to open an URL from the command line on your platform"
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ class Object
32
+ include UtilityBelt::Google
33
+ end if Object.const_defined? :IRB
@@ -0,0 +1,10 @@
1
+ class Hash
2
+ alias :+ :merge
3
+ def -(other)
4
+ if other.is_a? Hash
5
+ reject { |k,v| other[k] == v }
6
+ else
7
+ reject { |k,v| k == other }
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,78 @@
1
+ # Giles Bowkett, Greg Brown, and several audience members from Giles' Ruby East presentation.
2
+ require 'tempfile'
3
+ class InteractiveEditor
4
+ DEBIAN_SENSIBLE_EDITOR = "/usr/bin/sensible-editor"
5
+ MACOSX_OPEN_CMD = "open"
6
+ XDG_OPEN = "/usr/bin/xdg-open"
7
+
8
+ def self.sensible_editor
9
+ return ENV["VISUAL"] if ENV["VISUAL"]
10
+ return ENV["EDITOR"] if ENV["EDITOR"]
11
+ return MACOSX_OPEN_CMD if Platform::IMPL == :macosx
12
+ if Platform::IMPL == :linux
13
+ if File.executable?(XDG_OPEN)
14
+ return XDG_OPEN
15
+ end
16
+ if File.executable?(DEBIAN_SENSIBLE_EDITOR)
17
+ return DEBIAN_SENSIBLE_EDITOR
18
+ end
19
+ end
20
+ raise "Could not determine what editor to use. Please specify."
21
+ end
22
+
23
+ attr_accessor :editor
24
+ def initialize(editor = :vim)
25
+ @editor = editor.to_s
26
+ if @editor == "mate"
27
+ @editor = "mate -w"
28
+ end
29
+ end
30
+ def edit_interactively
31
+ unless @file
32
+ @file = Tempfile.new("irb_tempfile")
33
+ end
34
+ system("#{@editor} #{@file.path}")
35
+ Object.class_eval(`cat #{@file.path}`)
36
+ rescue Exception => error
37
+ puts error
38
+ end
39
+ end
40
+
41
+ module InteractiveEditing
42
+ def edit_interactively(editor = InteractiveEditor.sensible_editor)
43
+ unless IRB.conf[:interactive_editors] && IRB.conf[:interactive_editors][editor]
44
+ IRB.conf[:interactive_editors] ||= {}
45
+ IRB.conf[:interactive_editors][editor] = InteractiveEditor.new(editor)
46
+ end
47
+ IRB.conf[:interactive_editors][editor].edit_interactively
48
+ end
49
+
50
+ def handling_jruby_bug(&block)
51
+ if RUBY_PLATFORM =~ /java/
52
+ puts "JRuby IRB has a bug which prevents successful IRB vi/emacs editing."
53
+ puts "The JRuby team is aware of this and working on it."
54
+ puts "(http://jira.codehaus.org/browse/JRUBY-2049)"
55
+ else
56
+ yield
57
+ end
58
+ end
59
+
60
+ def vi
61
+ handling_jruby_bug {edit_interactively(:vim)}
62
+ end
63
+
64
+ def mate
65
+ edit_interactively(:mate)
66
+ end
67
+
68
+ # TODO: Hardcore Emacs users use emacsclient or gnuclient to open documents in
69
+ # their existing sessions, rather than starting a brand new Emacs process.
70
+ def emacs
71
+ handling_jruby_bug {edit_interactively(:emacs)}
72
+ end
73
+ end
74
+
75
+ # Since we only intend to use this from the IRB command line, I see no reason to
76
+ # extend the entire Object class with this module when we can just extend the
77
+ # IRB main object.
78
+ self.extend InteractiveEditing if Object.const_defined? :IRB