rum 0.0.1-x86-mingw32
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.
- data/CHANGELOG +3 -0
 - data/README +30 -0
 - data/Rakefile +134 -0
 - data/bin/rum-client +124 -0
 - data/doc/basic.rb +10 -0
 - data/doc/doc.html +602 -0
 - data/doc/example.rb +59 -0
 - data/doc/reference.rb +415 -0
 - data/doc/resources/bg.png +0 -0
 - data/doc/resources/bottom.png +0 -0
 - data/doc/resources/build.rb +235 -0
 - data/doc/resources/doc.haml +167 -0
 - data/doc/resources/emacs-auto-completion.png +0 -0
 - data/doc/resources/flash.png +0 -0
 - data/doc/resources/highlight.css +94 -0
 - data/doc/resources/intro.rb +17 -0
 - data/doc/resources/left.png +0 -0
 - data/doc/resources/logo.png +0 -0
 - data/doc/resources/screen.css +420 -0
 - data/doc/resources/screenshot.png +0 -0
 - data/doc/resources/top.png +0 -0
 - data/ext/mac/keyboard_hook/English.lproj/InfoPlist.strings +0 -0
 - data/ext/mac/keyboard_hook/Event.h +17 -0
 - data/ext/mac/keyboard_hook/Event.m +18 -0
 - data/ext/mac/keyboard_hook/EventTap.h +11 -0
 - data/ext/mac/keyboard_hook/EventTap.m +77 -0
 - data/ext/mac/keyboard_hook/Info.plist +26 -0
 - data/ext/mac/keyboard_hook/KeyboardHook.xcodeproj/TemplateIcon.icns +0 -0
 - data/ext/mac/keyboard_hook/KeyboardHook.xcodeproj/project.pbxproj +323 -0
 - data/ext/mac/keyboard_hook/KeyboardHook_Prefix.pch +7 -0
 - data/ext/mac/keyboard_hook/version.plist +16 -0
 - data/ext/windows/keyboard_hook/extconf.rb +2 -0
 - data/ext/windows/keyboard_hook/keyboard_hook.c +126 -0
 - data/ext/windows/system/autohotkey_stuff.c +255 -0
 - data/ext/windows/system/autohotkey_stuff.h +2 -0
 - data/ext/windows/system/clipboard_watcher.c +58 -0
 - data/ext/windows/system/clipboard_watcher.h +2 -0
 - data/ext/windows/system/extconf.rb +3 -0
 - data/ext/windows/system/input_box.c +239 -0
 - data/ext/windows/system/input_box.h +4 -0
 - data/ext/windows/system/system.c +273 -0
 - data/lib/rum.rb +4 -0
 - data/lib/rum/apps.rb +4 -0
 - data/lib/rum/barrel.rb +157 -0
 - data/lib/rum/barrel/emacs.rb +44 -0
 - data/lib/rum/barrel/emacs_client.rb +74 -0
 - data/lib/rum/core.rb +125 -0
 - data/lib/rum/dsl.rb +109 -0
 - data/lib/rum/gui.rb +93 -0
 - data/lib/rum/help.rb +128 -0
 - data/lib/rum/hotkey_core.rb +479 -0
 - data/lib/rum/mac.rb +18 -0
 - data/lib/rum/mac/app.rb +4 -0
 - data/lib/rum/mac/apps.rb +19 -0
 - data/lib/rum/mac/gui.rb +26 -0
 - data/lib/rum/mac/gui/growl.rb +54 -0
 - data/lib/rum/mac/irb/completion.rb +207 -0
 - data/lib/rum/mac/keyboard_hook.rb +73 -0
 - data/lib/rum/mac/layouts.rb +146 -0
 - data/lib/rum/mac/system.rb +45 -0
 - data/lib/rum/remote.rb +48 -0
 - data/lib/rum/server.rb +92 -0
 - data/lib/rum/windows.rb +23 -0
 - data/lib/rum/windows/app.rb +72 -0
 - data/lib/rum/windows/apps.rb +25 -0
 - data/lib/rum/windows/gui.rb +116 -0
 - data/lib/rum/windows/keyboard.rb +80 -0
 - data/lib/rum/windows/keyboard_hook.rb +20 -0
 - data/lib/rum/windows/keyboard_hook.so +0 -0
 - data/lib/rum/windows/layouts.rb +232 -0
 - data/lib/rum/windows/system.rb +310 -0
 - data/lib/rum/windows/system.so +0 -0
 - data/lib/rum/windows/system_foreign_functions.rb +129 -0
 - data/rum.gemspec +14 -0
 - metadata +156 -0
 
| 
         @@ -0,0 +1,45 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rum
         
     | 
| 
      
 2 
     | 
    
         
            +
              module System
         
     | 
| 
      
 3 
     | 
    
         
            +
                extend self
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def applescript src
         
     | 
| 
      
 6 
     | 
    
         
            +
                  pointer = Pointer.new_with_type("@")
         
     | 
| 
      
 7 
     | 
    
         
            +
                  as = NSAppleScript.alloc.initWithSource(src)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  as.executeAndReturnError(pointer)  
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
                
         
     | 
| 
      
 11 
     | 
    
         
            +
                def start *args
         
     | 
| 
      
 12 
     | 
    
         
            +
                  system 'open', *args
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def escape_shell_word str
         
     | 
| 
      
 16 
     | 
    
         
            +
                  if str.empty? or %r{\A[0-9A-Za-z+,./:=@_-]+\z} =~ str
         
     | 
| 
      
 17 
     | 
    
         
            +
                    str
         
     | 
| 
      
 18 
     | 
    
         
            +
                  else
         
     | 
| 
      
 19 
     | 
    
         
            +
                    result = ''
         
     | 
| 
      
 20 
     | 
    
         
            +
                    str.scan(/('+)|[^']+/) {
         
     | 
| 
      
 21 
     | 
    
         
            +
                      if $1
         
     | 
| 
      
 22 
     | 
    
         
            +
                        result << %q{\'} * $1.length
         
     | 
| 
      
 23 
     | 
    
         
            +
                      else
         
     | 
| 
      
 24 
     | 
    
         
            +
                        result << "'#{$&}'"
         
     | 
| 
      
 25 
     | 
    
         
            +
                      end
         
     | 
| 
      
 26 
     | 
    
         
            +
                    }
         
     | 
| 
      
 27 
     | 
    
         
            +
                    result
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def applescript_quote_string str
         
     | 
| 
      
 32 
     | 
    
         
            +
                  str.gsub!('\\', '\\\\\\\\')
         
     | 
| 
      
 33 
     | 
    
         
            +
                  str.gsub!('"', '\\"')
         
     | 
| 
      
 34 
     | 
    
         
            +
                  '"' << str << '"'
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def spawn_in_terminal(*args)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  close = args.delete :close_if_successful
         
     | 
| 
      
 39 
     | 
    
         
            +
                  command = args.map { |arg| escape_shell_word(arg) }.join(' ')
         
     | 
| 
      
 40 
     | 
    
         
            +
                  command << ';[ $? -eq 0 ] && exit' if close
         
     | 
| 
      
 41 
     | 
    
         
            +
                  command = applescript_quote_string(command)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  applescript 'tell application "Terminal" to do script ' + command
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/rum/remote.rb
    ADDED
    
    | 
         @@ -0,0 +1,48 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'socket'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Rum
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Remote
         
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(port=Remote.default_port)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @connection = Connection.new(TCPSocket.open('127.0.0.1', port))
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def eval code
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @connection.dispatch code
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @connection.receive
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def disconnect
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @connection.close
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def self.default_port
         
     | 
| 
      
 19 
     | 
    
         
            +
                  if (port = ENV['RUM_PORT'].to_i) and port.nonzero?
         
     | 
| 
      
 20 
     | 
    
         
            +
                    port
         
     | 
| 
      
 21 
     | 
    
         
            +
                  else
         
     | 
| 
      
 22 
     | 
    
         
            +
                    1994
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                module Connection
         
     | 
| 
      
 27 
     | 
    
         
            +
                  module Messaging
         
     | 
| 
      
 28 
     | 
    
         
            +
                    # Assumes message is not larger than 4,3 GB ((2**(4*8) - 1) bytes)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    def dispatch(msg)
         
     | 
| 
      
 30 
     | 
    
         
            +
                      msg.encode! Encoding::UTF_8
         
     | 
| 
      
 31 
     | 
    
         
            +
                      msg.force_encoding Encoding::BINARY
         
     | 
| 
      
 32 
     | 
    
         
            +
                      write([msg.length].pack('N') + msg)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
                    
         
     | 
| 
      
 35 
     | 
    
         
            +
                    def receive
         
     | 
| 
      
 36 
     | 
    
         
            +
                      if message_size = read(4) # sizeof (N)
         
     | 
| 
      
 37 
     | 
    
         
            +
                        message_size = message_size.unpack('N')[0]	
         
     | 
| 
      
 38 
     | 
    
         
            +
                        read(message_size).force_encoding(Encoding::UTF_8)
         
     | 
| 
      
 39 
     | 
    
         
            +
                      end
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                  
         
     | 
| 
      
 43 
     | 
    
         
            +
                  def Connection.new(stream)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    stream.extend Messaging
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/rum/server.rb
    ADDED
    
    | 
         @@ -0,0 +1,92 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rum/remote'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Rum
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Server
         
     | 
| 
      
 5 
     | 
    
         
            +
                module_function
         
     | 
| 
      
 6 
     | 
    
         
            +
                
         
     | 
| 
      
 7 
     | 
    
         
            +
                # This makes it easier for code to check if it runs inside the server thread.
         
     | 
| 
      
 8 
     | 
    
         
            +
                def thread
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @thread
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def start
         
     | 
| 
      
 13 
     | 
    
         
            +
                  return if @thread
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @thread = Thread.new do
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @server = TCPServer.new('127.0.0.1', Remote.default_port)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    puts "Server started."
         
     | 
| 
      
 17 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 18 
     | 
    
         
            +
                      @connection = nil
         
     | 
| 
      
 19 
     | 
    
         
            +
                      loop do
         
     | 
| 
      
 20 
     | 
    
         
            +
                        @connection = Remote::Connection.new(@server.accept)
         
     | 
| 
      
 21 
     | 
    
         
            +
                        handle(@connection)
         
     | 
| 
      
 22 
     | 
    
         
            +
                        @connection.close
         
     | 
| 
      
 23 
     | 
    
         
            +
                      end
         
     | 
| 
      
 24 
     | 
    
         
            +
                    ensure # clean up when thread gets killed
         
     | 
| 
      
 25 
     | 
    
         
            +
                      close_connections
         
     | 
| 
      
 26 
     | 
    
         
            +
                    end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                # Temporary hack.
         
     | 
| 
      
 31 
     | 
    
         
            +
                # MacRuby crashes on the ensure clause above when
         
     | 
| 
      
 32 
     | 
    
         
            +
                # the server thread is killed.
         
     | 
| 
      
 33 
     | 
    
         
            +
                # This function allows for manually closing the connections.
         
     | 
| 
      
 34 
     | 
    
         
            +
                def close_connections
         
     | 
| 
      
 35 
     | 
    
         
            +
                  [@server, @connection].compact.each { |e| e.close unless e.closed? }
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def stop
         
     | 
| 
      
 39 
     | 
    
         
            +
                  if @thread
         
     | 
| 
      
 40 
     | 
    
         
            +
                    @thread.kill
         
     | 
| 
      
 41 
     | 
    
         
            +
                    # Kill can return before the thread has finished execution. A Ruby bug?
         
     | 
| 
      
 42 
     | 
    
         
            +
                    @thread.join
         
     | 
| 
      
 43 
     | 
    
         
            +
                    @thread = nil
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                EvalBinding = TOPLEVEL_BINDING
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def handle(connection)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  return nil unless message = connection.receive
         
     | 
| 
      
 51 
     | 
    
         
            +
                  result = begin
         
     | 
| 
      
 52 
     | 
    
         
            +
                             eval(message, EvalBinding).inspect
         
     | 
| 
      
 53 
     | 
    
         
            +
                           rescue Exception => exception
         
     | 
| 
      
 54 
     | 
    
         
            +
                             error_message(exception)
         
     | 
| 
      
 55 
     | 
    
         
            +
                           end
         
     | 
| 
      
 56 
     | 
    
         
            +
                  connection.dispatch(result)
         
     | 
| 
      
 57 
     | 
    
         
            +
                rescue SystemCallError # connection errors
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def error_message(exception)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  # Hide the internals from the backtrace
         
     | 
| 
      
 62 
     | 
    
         
            +
                  backtrace = exception.backtrace.reject { |frame| frame =~ /^#{__FILE__}/ }
         
     | 
| 
      
 63 
     | 
    
         
            +
                  msg = ["Rum-Server: Evaluation Error."]
         
     | 
| 
      
 64 
     | 
    
         
            +
                  msg << "#{exception.class}: #{exception}"
         
     | 
| 
      
 65 
     | 
    
         
            +
                  msg += backtrace
         
     | 
| 
      
 66 
     | 
    
         
            +
                  msg.join "\n"
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                module IRBCompletion
         
     | 
| 
      
 70 
     | 
    
         
            +
                  Glue = 'binding = Rum::Server::EvalBinding
         
     | 
| 
      
 71 
     | 
    
         
            +
                          workspace = Struct.new(:binding).new(binding)
         
     | 
| 
      
 72 
     | 
    
         
            +
                          context = Struct.new(:workspace).new(workspace)
         
     | 
| 
      
 73 
     | 
    
         
            +
                          @CONF = { MAIN_CONTEXT: context }
         
     | 
| 
      
 74 
     | 
    
         
            +
                          
         
     | 
| 
      
 75 
     | 
    
         
            +
                          def IRB.conf
         
     | 
| 
      
 76 
     | 
    
         
            +
                            @CONF
         
     | 
| 
      
 77 
     | 
    
         
            +
                          end'
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  def self.setup
         
     | 
| 
      
 80 
     | 
    
         
            +
                    unless defined? IRB
         
     | 
| 
      
 81 
     | 
    
         
            +
                      # Since version 0.7, MacRuby ships with an incompatible IRB
         
     | 
| 
      
 82 
     | 
    
         
            +
                      # distribution called dietirb. Mac Rum includes a partial
         
     | 
| 
      
 83 
     | 
    
         
            +
                      # copy of the original IRB.
         
     | 
| 
      
 84 
     | 
    
         
            +
                      require Rum::Platform == :mac ? 'rum/mac/irb/completion' : 'irb/completion'
         
     | 
| 
      
 85 
     | 
    
         
            +
                      IRB.module_eval(Glue)
         
     | 
| 
      
 86 
     | 
    
         
            +
                    end
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                IRBCompletion.setup
         
     | 
| 
      
 91 
     | 
    
         
            +
              end
         
     | 
| 
      
 92 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/rum/windows.rb
    ADDED
    
    | 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rum/windows/system'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'rum/windows/keyboard_hook'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'rum/windows/keyboard'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rum/windows/gui'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'rum/windows/app'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'rum/windows/layouts'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module Rum
         
     | 
| 
      
 9 
     | 
    
         
            +
              Platform = :windows
         
     | 
| 
      
 10 
     | 
    
         
            +
              
         
     | 
| 
      
 11 
     | 
    
         
            +
              def self.restart_platform_specific
         
     | 
| 
      
 12 
     | 
    
         
            +
                Rum::Server.stop
         
     | 
| 
      
 13 
     | 
    
         
            +
                System.spawn_in_terminal('ruby', $PROGRAM_NAME)
         
     | 
| 
      
 14 
     | 
    
         
            +
                sleep 0.01 # This prevents a strange lag. Wow.
         
     | 
| 
      
 15 
     | 
    
         
            +
                System.terminal_window.close
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              class HotkeyProcessor
         
     | 
| 
      
 19 
     | 
    
         
            +
                def inhibit_modifier_action
         
     | 
| 
      
 20 
     | 
    
         
            +
                  System.send_keypress @layout['control']
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,72 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rum
         
     | 
| 
      
 2 
     | 
    
         
            +
              class App
         
     | 
| 
      
 3 
     | 
    
         
            +
                include System
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                @@apps = {}
         
     | 
| 
      
 6 
     | 
    
         
            +
                
         
     | 
| 
      
 7 
     | 
    
         
            +
                def self.add(app)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @@apps[app.binary] = app
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
                
         
     | 
| 
      
 11 
     | 
    
         
            +
                def self.remove(app)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @@apps.delete(app.binary)
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def self.apps
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @@apps
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def self.for_exe(exe)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @@apps[exe.downcase]
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                attr_accessor :path, :binary, :matcher
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def initialize(path, *matcher)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @path = append_path_to_programfiles_if_relative(path)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @binary = File.basename(@path).sub(/\.exe$/, '').downcase
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @matcher = WindowMatcher.new(*matcher)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  App.add(self)
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def append_path_to_programfiles_if_relative(path)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  if path !~ /^\w:|^%/
         
     | 
| 
      
 34 
     | 
    
         
            +
                    path = File.join(ENV['PROGRAMFILES'].gsub("\\", '/'), path)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                  path
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def binary=(bin)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  App.remove(self)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @binary = bin.downcase
         
     | 
| 
      
 42 
     | 
    
         
            +
                  App.add(self)
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                # Returns 'true' if the application window could be activated instantly.
         
     | 
| 
      
 46 
     | 
    
         
            +
                def activate
         
     | 
| 
      
 47 
     | 
    
         
            +
                  window = @matcher.find
         
     | 
| 
      
 48 
     | 
    
         
            +
                  if window
         
     | 
| 
      
 49 
     | 
    
         
            +
                    window.show
         
     | 
| 
      
 50 
     | 
    
         
            +
                  else
         
     | 
| 
      
 51 
     | 
    
         
            +
                    run
         
     | 
| 
      
 52 
     | 
    
         
            +
                    false
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                def run
         
     | 
| 
      
 57 
     | 
    
         
            +
                  start @path
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def to_matcher
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @matcher
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                def active?
         
     | 
| 
      
 65 
     | 
    
         
            +
                  @matcher.active?
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                def window
         
     | 
| 
      
 69 
     | 
    
         
            +
                  @matcher.find
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            Emacs = App.new('', nil, 'Emacs')
         
     | 
| 
      
 3 
     | 
    
         
            +
            Emacs.binary = 'emacs'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rum/barrel/emacs'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Firefox = App.new('mozilla firefox/firefox', /firefox/, 'MozillaWindowClass')
         
     | 
| 
      
 7 
     | 
    
         
            +
            def Firefox.activate_and_focus_address_bar
         
     | 
| 
      
 8 
     | 
    
         
            +
              Keyboard.type '(ctrl l)' if activate
         
     | 
| 
      
 9 
     | 
    
         
            +
            end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            Photoshop = App.new('Adobe/Adobe Photoshop CS5/Photoshop', nil, 'Photoshop')
         
     | 
| 
      
 12 
     | 
    
         
            +
            class << Photoshop
         
     | 
| 
      
 13 
     | 
    
         
            +
              def next_blend_mode
         
     | 
| 
      
 14 
     | 
    
         
            +
                if Rum.layout['ö'] # german layout
         
     | 
| 
      
 15 
     | 
    
         
            +
                  type '(shift 0)'
         
     | 
| 
      
 16 
     | 
    
         
            +
                else
         
     | 
| 
      
 17 
     | 
    
         
            +
                  type '(shift +)'
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              def previous_blend_mode
         
     | 
| 
      
 22 
     | 
    
         
            +
                type '(shift -)'
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,116 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rum
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Gui
         
     | 
| 
      
 3 
     | 
    
         
            +
                def goto path
         
     | 
| 
      
 4 
     | 
    
         
            +
                  if File.directory? path
         
     | 
| 
      
 5 
     | 
    
         
            +
                    System.start path
         
     | 
| 
      
 6 
     | 
    
         
            +
                  else
         
     | 
| 
      
 7 
     | 
    
         
            +
                    Gui.message "Can't visit a file in Windows Explorer."
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
                
         
     | 
| 
      
 11 
     | 
    
         
            +
                def open_file file, line=nil
         
     | 
| 
      
 12 
     | 
    
         
            +
                  System.start file
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                private
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def browse_backend url
         
     | 
| 
      
 18 
     | 
    
         
            +
                  System.start url
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                module WindowsDialogs
         
     | 
| 
      
 22 
     | 
    
         
            +
                  private
         
     | 
| 
      
 23 
     | 
    
         
            +
                  def alert_backend text, title
         
     | 
| 
      
 24 
     | 
    
         
            +
                    System.message_box text, title
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  
         
     | 
| 
      
 27 
     | 
    
         
            +
                  def message_backend text, title, sticky, callback
         
     | 
| 
      
 28 
     | 
    
         
            +
                    alert text, title
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def read_backend text, title, initial_value
         
     | 
| 
      
 32 
     | 
    
         
            +
                    System.input_box text, title, initial_value
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                use WindowsDialogs
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                module Growl
         
     | 
| 
      
 39 
     | 
    
         
            +
                  Message = 'message'
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  private
         
     | 
| 
      
 42 
     | 
    
         
            +
                  
         
     | 
| 
      
 43 
     | 
    
         
            +
                  def message_backend(text, title, sticky, callback)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    unless title
         
     | 
| 
      
 45 
     | 
    
         
            +
                      title = text
         
     | 
| 
      
 46 
     | 
    
         
            +
                      text = nil
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                    # ruby_gntp raises an error when 'title' is nil or pure whitespace.
         
     | 
| 
      
 49 
     | 
    
         
            +
                    title = 'empty text' if title.to_s.strip.empty?
         
     | 
| 
      
 50 
     | 
    
         
            +
                    if callback
         
     | 
| 
      
 51 
     | 
    
         
            +
                      on_click = lambda { |event| callback.call if event[:callback_result] == "CLICK" }
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
                    
         
     | 
| 
      
 54 
     | 
    
         
            +
                    Growl.client.notify(name: Message, title: title,
         
     | 
| 
      
 55 
     | 
    
         
            +
                                        text: text, sticky: sticky, &on_click)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  end
         
     | 
| 
      
 57 
     | 
    
         
            +
                  
         
     | 
| 
      
 58 
     | 
    
         
            +
                  module_function
         
     | 
| 
      
 59 
     | 
    
         
            +
                  
         
     | 
| 
      
 60 
     | 
    
         
            +
                  def auto_setup
         
     | 
| 
      
 61 
     | 
    
         
            +
                    require 'ruby_gntp'
         
     | 
| 
      
 62 
     | 
    
         
            +
                    @growl = GNTP.new("Rum")
         
     | 
| 
      
 63 
     | 
    
         
            +
                    @growl.register(notifications: [{name: Message, enabled: true}])
         
     | 
| 
      
 64 
     | 
    
         
            +
                    true
         
     | 
| 
      
 65 
     | 
    
         
            +
                  rescue Errno::ECONNREFUSED # Growl not running
         
     | 
| 
      
 66 
     | 
    
         
            +
                    @growl = nil
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                  def client
         
     | 
| 
      
 70 
     | 
    
         
            +
                    @growl or auto_setup and @growl
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                module EmacsInteraction
         
     | 
| 
      
 75 
     | 
    
         
            +
                  private
         
     | 
| 
      
 76 
     | 
    
         
            +
                  
         
     | 
| 
      
 77 
     | 
    
         
            +
                  def interaction(*args)
         
     | 
| 
      
 78 
     | 
    
         
            +
                    emacs = Emacs.window
         
     | 
| 
      
 79 
     | 
    
         
            +
                    return '' unless emacs
         
     | 
| 
      
 80 
     | 
    
         
            +
                    unless (emacs_already_active = emacs.active?)
         
     | 
| 
      
 81 
     | 
    
         
            +
                      old = System.active_window
         
     | 
| 
      
 82 
     | 
    
         
            +
                      emacs.move(400, 400, 800, 300)
         
     | 
| 
      
 83 
     | 
    
         
            +
                      emacs.show
         
     | 
| 
      
 84 
     | 
    
         
            +
                    end
         
     | 
| 
      
 85 
     | 
    
         
            +
                    result = unpack(Emacs.funcall(*args))
         
     | 
| 
      
 86 
     | 
    
         
            +
                    unless emacs_already_active
         
     | 
| 
      
 87 
     | 
    
         
            +
                      wait { old.active? } unless old.show
         
     | 
| 
      
 88 
     | 
    
         
            +
                      emacs.maximize
         
     | 
| 
      
 89 
     | 
    
         
            +
                    end
         
     | 
| 
      
 90 
     | 
    
         
            +
                    result
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                  def unpack(output)
         
     | 
| 
      
 94 
     | 
    
         
            +
                    # If we don't get a string back something has gone wrong.
         
     | 
| 
      
 95 
     | 
    
         
            +
                    raise 'emacs returned no string: ' << output unless output[0] == ?"
         
     | 
| 
      
 96 
     | 
    
         
            +
                    # The first line contains the status (1 or 0),
         
     | 
| 
      
 97 
     | 
    
         
            +
                    # the second line contains additional output.
         
     | 
| 
      
 98 
     | 
    
         
            +
                    # See telemacs-format-output.
         
     | 
| 
      
 99 
     | 
    
         
            +
                    output = Emacs.unquote(output)
         
     | 
| 
      
 100 
     | 
    
         
            +
                    if output =~ /\n$/
         
     | 
| 
      
 101 
     | 
    
         
            +
                      ''
         
     | 
| 
      
 102 
     | 
    
         
            +
                    else
         
     | 
| 
      
 103 
     | 
    
         
            +
                      output = output.split(/\n/)
         
     | 
| 
      
 104 
     | 
    
         
            +
                      output[1] or (output[0] == '1' ?  true : nil)
         
     | 
| 
      
 105 
     | 
    
         
            +
                    end
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                  def choose_backend prompt, choices
         
     | 
| 
      
 109 
     | 
    
         
            +
                    prompt = prompt ? Emacs.quote(prompt) : 'nil'
         
     | 
| 
      
 110 
     | 
    
         
            +
                    fn = 'selekt-external-fast'
         
     | 
| 
      
 111 
     | 
    
         
            +
                    result = interaction(fn, prompt, *choices.map { |item| Emacs.quote(item.to_s) })
         
     | 
| 
      
 112 
     | 
    
         
            +
                    choices[result.to_i] if result
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
      
 115 
     | 
    
         
            +
              end
         
     | 
| 
      
 116 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,80 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'strscan'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Rum
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Keyboard
         
     | 
| 
      
 5 
     | 
    
         
            +
                extend self
         
     | 
| 
      
 6 
     | 
    
         
            +
                
         
     | 
| 
      
 7 
     | 
    
         
            +
                def type(key_sequence, *args)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  release_core_modifiers unless args.include? :blind
         
     | 
| 
      
 9 
     | 
    
         
            +
                  type_sequence(key_sequence, args.include?(:slow))
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
                
         
     | 
| 
      
 12 
     | 
    
         
            +
                def type!(key_sequence, *args)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  release_core_modifiers unless args.include? :blind
         
     | 
| 
      
 14 
     | 
    
         
            +
                  type_sequence_literally(key_sequence, args.include?(:slow))
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def release_core_modifiers
         
     | 
| 
      
 18 
     | 
    
         
            +
                  pressed = Rum.hotkey_processor.pressed_modifiers
         
     | 
| 
      
 19 
     | 
    
         
            +
                  to_release = Rum.layout.core_modifiers.keys.select { |mod| pressed[mod] }
         
     | 
| 
      
 20 
     | 
    
         
            +
                  to_release.each { |key| System.send_key_event key, false }
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                private
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def type_sequence_literally(key_sequence, slow)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  key_sequence.chars.each do |char|
         
     | 
| 
      
 27 
     | 
    
         
            +
                    if (key = Rum.layout[char])
         
     | 
| 
      
 28 
     | 
    
         
            +
                      System.send_keypress key
         
     | 
| 
      
 29 
     | 
    
         
            +
                      sleep 0.01 if slow
         
     | 
| 
      
 30 
     | 
    
         
            +
                    elsif (translation = Rum.layout.translations[char])
         
     | 
| 
      
 31 
     | 
    
         
            +
                      type_sequence(translation, slow)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                def type_sequence(key_sequence, slow)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  s = StringScanner.new(key_sequence)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  pressed_keys = []
         
     | 
| 
      
 39 
     | 
    
         
            +
                  while (char = s.getch)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    case char
         
     | 
| 
      
 41 
     | 
    
         
            +
                    when '\\'
         
     | 
| 
      
 42 
     | 
    
         
            +
                      down_and_up(s.getch, slow)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    when '('
         
     | 
| 
      
 44 
     | 
    
         
            +
                      key = s.scan(/[^() ]+/)
         
     | 
| 
      
 45 
     | 
    
         
            +
                      s.skip /\ /
         
     | 
| 
      
 46 
     | 
    
         
            +
                      down key
         
     | 
| 
      
 47 
     | 
    
         
            +
                      pressed_keys << key
         
     | 
| 
      
 48 
     | 
    
         
            +
                    when ')'
         
     | 
| 
      
 49 
     | 
    
         
            +
                      up pressed_keys.pop
         
     | 
| 
      
 50 
     | 
    
         
            +
                    else
         
     | 
| 
      
 51 
     | 
    
         
            +
                      down_and_up(char, slow)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
                    sleep 0.01 if slow
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                  pressed_keys.reverse_each { |key| up key }
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                def send_key(key, down)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  if id = Rum.layout[key]
         
     | 
| 
      
 60 
     | 
    
         
            +
                    System.send_key_event id, down
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                def down(key)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  send_key key, true
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                def up(key)
         
     | 
| 
      
 69 
     | 
    
         
            +
                  send_key key, false
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                def down_and_up(char, slow)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  if (key = Rum.layout[char])
         
     | 
| 
      
 74 
     | 
    
         
            +
                    System.send_keypress key
         
     | 
| 
      
 75 
     | 
    
         
            +
                  elsif (key_sequence = Rum.layout.translations[char])
         
     | 
| 
      
 76 
     | 
    
         
            +
                    type_sequence(key_sequence, slow)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
              end
         
     | 
| 
      
 80 
     | 
    
         
            +
            end
         
     |