rum 0.0.1-universal-darwin-10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/CHANGELOG +3 -0
  2. data/README +30 -0
  3. data/Rakefile +134 -0
  4. data/bin/rum-client +124 -0
  5. data/doc/basic.rb +10 -0
  6. data/doc/doc.html +602 -0
  7. data/doc/example.rb +59 -0
  8. data/doc/reference.rb +415 -0
  9. data/doc/resources/bg.png +0 -0
  10. data/doc/resources/bottom.png +0 -0
  11. data/doc/resources/build.rb +235 -0
  12. data/doc/resources/doc.haml +167 -0
  13. data/doc/resources/emacs-auto-completion.png +0 -0
  14. data/doc/resources/flash.png +0 -0
  15. data/doc/resources/highlight.css +94 -0
  16. data/doc/resources/intro.rb +17 -0
  17. data/doc/resources/left.png +0 -0
  18. data/doc/resources/logo.png +0 -0
  19. data/doc/resources/screen.css +420 -0
  20. data/doc/resources/screenshot.png +0 -0
  21. data/doc/resources/top.png +0 -0
  22. data/ext/mac/keyboard_hook/English.lproj/InfoPlist.strings +0 -0
  23. data/ext/mac/keyboard_hook/Event.h +17 -0
  24. data/ext/mac/keyboard_hook/Event.m +18 -0
  25. data/ext/mac/keyboard_hook/EventTap.h +11 -0
  26. data/ext/mac/keyboard_hook/EventTap.m +77 -0
  27. data/ext/mac/keyboard_hook/Info.plist +26 -0
  28. data/ext/mac/keyboard_hook/KeyboardHook.xcodeproj/TemplateIcon.icns +0 -0
  29. data/ext/mac/keyboard_hook/KeyboardHook.xcodeproj/project.pbxproj +323 -0
  30. data/ext/mac/keyboard_hook/KeyboardHook_Prefix.pch +7 -0
  31. data/ext/mac/keyboard_hook/version.plist +16 -0
  32. data/ext/windows/keyboard_hook/extconf.rb +2 -0
  33. data/ext/windows/keyboard_hook/keyboard_hook.c +126 -0
  34. data/ext/windows/system/autohotkey_stuff.c +255 -0
  35. data/ext/windows/system/autohotkey_stuff.h +2 -0
  36. data/ext/windows/system/clipboard_watcher.c +58 -0
  37. data/ext/windows/system/clipboard_watcher.h +2 -0
  38. data/ext/windows/system/extconf.rb +3 -0
  39. data/ext/windows/system/input_box.c +239 -0
  40. data/ext/windows/system/input_box.h +4 -0
  41. data/ext/windows/system/system.c +273 -0
  42. data/lib/rum.rb +4 -0
  43. data/lib/rum/apps.rb +4 -0
  44. data/lib/rum/barrel.rb +157 -0
  45. data/lib/rum/barrel/emacs.rb +44 -0
  46. data/lib/rum/barrel/emacs_client.rb +74 -0
  47. data/lib/rum/core.rb +125 -0
  48. data/lib/rum/dsl.rb +109 -0
  49. data/lib/rum/gui.rb +93 -0
  50. data/lib/rum/help.rb +128 -0
  51. data/lib/rum/hotkey_core.rb +479 -0
  52. data/lib/rum/mac.rb +18 -0
  53. data/lib/rum/mac/app.rb +4 -0
  54. data/lib/rum/mac/apps.rb +19 -0
  55. data/lib/rum/mac/gui.rb +26 -0
  56. data/lib/rum/mac/gui/CocoaDialog.app/Contents/Info.plist +28 -0
  57. data/lib/rum/mac/gui/CocoaDialog.app/Contents/MacOS/CocoaDialog +0 -0
  58. data/lib/rum/mac/gui/CocoaDialog.app/Contents/Resources/Info.plist +28 -0
  59. data/lib/rum/mac/gui/CocoaDialog.app/Contents/Resources/InfoPlist.strings +0 -0
  60. data/lib/rum/mac/gui/CocoaDialog.app/Contents/Resources/Inputbox.nib/classes.nib +51 -0
  61. data/lib/rum/mac/gui/CocoaDialog.app/Contents/Resources/Inputbox.nib/info.nib +16 -0
  62. data/lib/rum/mac/gui/CocoaDialog.app/Contents/Resources/Inputbox.nib/keyedobjects.nib +0 -0
  63. data/lib/rum/mac/gui/CocoaDialog.app/Contents/Resources/MainMenu.nib/classes.nib +7 -0
  64. data/lib/rum/mac/gui/CocoaDialog.app/Contents/Resources/MainMenu.nib/info.nib +21 -0
  65. data/lib/rum/mac/gui/CocoaDialog.app/Contents/Resources/MainMenu.nib/info.nib.orig +21 -0
  66. data/lib/rum/mac/gui/CocoaDialog.app/Contents/Resources/MainMenu.nib/objects.nib +0 -0
  67. data/lib/rum/mac/gui/CocoaDialog.app/Contents/Resources/MainMenu.nib/objects.nib.orig +0 -0
  68. data/lib/rum/mac/gui/CocoaDialog.app/Contents/Resources/Msgbox.nib/classes.nib +27 -0
  69. data/lib/rum/mac/gui/CocoaDialog.app/Contents/Resources/Msgbox.nib/info.nib +16 -0
  70. data/lib/rum/mac/gui/CocoaDialog.app/Contents/Resources/Msgbox.nib/keyedobjects.nib +0 -0
  71. data/lib/rum/mac/gui/Growl.framework/Growl +0 -0
  72. data/lib/rum/mac/gui/Growl.framework/Versions/A/Growl +0 -0
  73. data/lib/rum/mac/gui/Growl.framework/Versions/A/Headers/Growl.h +6 -0
  74. data/lib/rum/mac/gui/Growl.framework/Versions/A/Headers/GrowlApplicationBridge-Carbon.h +780 -0
  75. data/lib/rum/mac/gui/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h +575 -0
  76. data/lib/rum/mac/gui/Growl.framework/Versions/A/Headers/GrowlDefines.h +348 -0
  77. data/lib/rum/mac/gui/Growl.framework/Versions/A/Resources/Info.plist +24 -0
  78. data/lib/rum/mac/gui/growl.rb +54 -0
  79. data/lib/rum/mac/irb/completion.rb +207 -0
  80. data/lib/rum/mac/keyboard_hook.rb +73 -0
  81. data/lib/rum/mac/keyboard_hook/KeyboardHook.framework/KeyboardHook +0 -0
  82. data/lib/rum/mac/keyboard_hook/KeyboardHook.framework/Versions/A/KeyboardHook +0 -0
  83. data/lib/rum/mac/keyboard_hook/KeyboardHook.framework/Versions/A/Resources/English.lproj/InfoPlist.strings +0 -0
  84. data/lib/rum/mac/keyboard_hook/KeyboardHook.framework/Versions/A/Resources/Info.plist +22 -0
  85. data/lib/rum/mac/layouts.rb +146 -0
  86. data/lib/rum/mac/system.rb +45 -0
  87. data/lib/rum/remote.rb +48 -0
  88. data/lib/rum/server.rb +92 -0
  89. data/lib/rum/windows.rb +23 -0
  90. data/lib/rum/windows/app.rb +72 -0
  91. data/lib/rum/windows/apps.rb +25 -0
  92. data/lib/rum/windows/gui.rb +116 -0
  93. data/lib/rum/windows/keyboard.rb +80 -0
  94. data/lib/rum/windows/keyboard_hook.rb +20 -0
  95. data/lib/rum/windows/layouts.rb +232 -0
  96. data/lib/rum/windows/system.rb +310 -0
  97. data/lib/rum/windows/system_foreign_functions.rb +129 -0
  98. data/rum.gemspec +14 -0
  99. metadata +166 -0
@@ -0,0 +1,3 @@
1
+ = 0.0.1
2
+ === 2011/06/4
3
+ * Hello World!
data/README ADDED
@@ -0,0 +1,30 @@
1
+ = Description
2
+ A cross-platform Hotkey and Macro utility, running on Windows and Mac OS.
3
+
4
+ = Synopsis
5
+ require 'rum'
6
+ Rum.layout.modifier 'caps'
7
+ 'caps f1'.do { message 'hi' }
8
+ Rum.start
9
+
10
+ = Documentation
11
+ Visit http://nonsequitur.github.com/rum for examples and a detailed reference.
12
+
13
+ = License
14
+ Rum is available under the MIT license (http://www.opensource.org/licenses/mit-license.php)
15
+ Copyright 2010-2011, The Rum Project
16
+
17
+ = Licenses of software that is bundled with some Rum distributions
18
+ == CocoaDialog
19
+ CocoaDialog is Copyright © 2004, Mark A. Stratman <mark@sporkstorms.org>
20
+ It is licensed under the GNU General Public License.
21
+ http://cocoadialog.sourceforge.net/
22
+
23
+ == Growl
24
+ Copyright (c) The Growl Project, 2004
25
+ All rights reserved.
26
+ http://growl.info/documentation/developer/bsd-license.txt
27
+
28
+ == AutoHotkey
29
+ GNU General Public License
30
+ http://www.autohotkey.com/docs/license.htm
@@ -0,0 +1,134 @@
1
+ require 'rake/clean'
2
+
3
+ CLEAN.include('ext/windows/keyboard_hook/*',
4
+ 'ext/windows/system/*',
5
+ 'ext/mac/keyboard_hook/build',
6
+ '*.gem',
7
+ '**/.DS_Store')
8
+ CLEAN.exclude('.c', '.h', 'extconf.rb')
9
+
10
+ CLOBBER.include('lib/rum/windows/keyboard_hook.so',
11
+ 'lib/rum/windows/system.so',
12
+ 'lib/rum/mac/keyboard_hook/KeyboardHook.framework',
13
+ 'doc/doc.html')
14
+
15
+ MAC_BINARIES = ['lib/rum/mac/keyboard_hook/KeyboardHook.framework',
16
+ 'lib/rum/mac/gui/Growl.framework',
17
+ 'lib/rum/mac/gui/CocoaDialog.app']
18
+
19
+ WINDOWS_BINARIES = ['lib/rum/windows/keyboard_hook.so',
20
+ 'lib/rum/windows/system.so']
21
+
22
+ namespace :ext do
23
+ namespace :windows do
24
+ InstallDir = 'lib/rum/windows'
25
+
26
+ extensions = [['ext/windows/keyboard_hook', 'keyboard_hook'],
27
+ ['ext/windows/system', 'system', 'input_box',
28
+ 'autohotkey_stuff', 'clipboard_watcher']]
29
+
30
+ extensions.each do |dir, ext, *deps|
31
+
32
+ extconf = "#{dir}/extconf.rb"
33
+
34
+ deps.map! do |dependency|
35
+ source = "#{dir}/#{dependency}.c"
36
+ obj = "#{dir}/#{dependency}.obj"
37
+ file source do
38
+ # Trigger automatic compiling of source in make
39
+ rm obj if File.exists? obj
40
+ end
41
+ source
42
+ end
43
+
44
+ file "#{InstallDir}/#{ext}.so" => ["#{dir}/#{ext}.c", extconf, *deps] do
45
+ Dir.chdir(dir) do
46
+ ruby 'extconf.rb'
47
+ system 'nmake'
48
+ system "mt -manifest #{ext}.so.manifest -outputresource:#{ext}.so;2"
49
+ end
50
+ mv "#{dir}/#{ext}.so", InstallDir
51
+ end
52
+ end
53
+
54
+ task :keyboard_hook => 'lib/rum/windows/keyboard_hook.so'
55
+ task :system => 'lib/rum/windows/system.so'
56
+ end
57
+ task :windows => ['windows:keyboard_hook', 'windows:system']
58
+
59
+ namespace :mac do
60
+ keyboard_hook = 'lib/rum/mac/keyboard_hook/KeyboardHook.framework'
61
+ xcode_output = 'ext/mac/keyboard_hook/build/release/KeyboardHook.framework'
62
+
63
+ file keyboard_hook => xcode_output do
64
+ rm_r keyboard_hook if File.exists? keyboard_hook
65
+ cp_r xcode_output, keyboard_hook
66
+ end
67
+
68
+ file xcode_output => FileList['ext/mac/keyboard_hook/*.m'] do
69
+ Dir.chdir('ext/mac/keyboard_hook') { system 'xcodebuild' }
70
+ end
71
+
72
+ task :keyboard_hook => keyboard_hook
73
+ end
74
+ task :mac => 'mac:keyboard_hook'
75
+ end
76
+
77
+ namespace :gem do
78
+ def common_spec
79
+ spec = eval(IO.read('rum.gemspec'))
80
+ yield spec
81
+ end
82
+
83
+ def build(spec)
84
+ Gem::Builder.new(spec).build
85
+ end
86
+
87
+ task :windows do
88
+ common_spec do |spec|
89
+ spec.files = FileList['**/*'].exclude(*CLEAN.to_a, *MAC_BINARIES)
90
+ spec.add_dependency('ruby_gntp', '>= 0.3.4')
91
+ spec.add_dependency('win32-api', '>= 1.4.8')
92
+ spec.add_dependency('win32-clipboard', '>= 0.5.2')
93
+ # mingw32 and mswin32 binaries can be used interchangeably
94
+ spec.platform = 'x86-mingw32'
95
+ build(spec)
96
+ spec.platform = 'x86-mswin32-60'
97
+ build(spec)
98
+ end
99
+ end
100
+
101
+ task :mac do
102
+ common_spec do |spec|
103
+ spec.platform = 'universal-darwin-10'
104
+ spec.files = FileList['**/*'].exclude(*CLEAN.to_a, *WINDOWS_BINARIES)
105
+ build(spec)
106
+ end
107
+ end
108
+
109
+ task :publish do
110
+
111
+ end
112
+ end
113
+ task :gem => ['gem:windows', 'gem:mac']
114
+
115
+ namespace :doc do
116
+ doc = 'doc/doc.html'
117
+ doc_files = ['doc/resources/doc.haml', 'doc/resources/intro.rb', 'doc/basic.rb',
118
+ 'doc/example.rb','doc/reference.rb']
119
+ task :build => doc
120
+
121
+ build_script = 'doc/resources/build.rb'
122
+ file doc => [*doc_files, build_script] do
123
+ require_relative build_script
124
+ Doc.new(*doc_files, dir: File.dirname(__FILE__), output: doc).build
125
+ end
126
+ end
127
+ task :doc => 'doc:build'
128
+
129
+ case RUBY_PLATFORM
130
+ when /mswin|mingw/ then task :ext => 'ext:windows'
131
+ when /darwin/ then task :ext => 'ext:mac'
132
+ else raise 'Platform not supported.'
133
+ end
134
+ task :build => [:ext, :doc]
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Client
4
+ module_function
5
+
6
+ def connect
7
+ @remote = Rum::Remote.new
8
+ rescue SystemCallError
9
+ puts "Rum Client: Connecting failed. Rum Server not responding."
10
+ end
11
+
12
+ class NilResponse < StandardError; end
13
+
14
+ def eval(code)
15
+ if connect
16
+ result = @remote.eval(code) or raise NilResponse
17
+ @remote.disconnect
18
+ result
19
+ end
20
+ rescue SystemCallError, NilResponse # Connection Error
21
+ @remote.disconnect
22
+ puts "Rum Client: Connection to Rum Server lost."
23
+ end
24
+ end
25
+
26
+ module RemoteIRB
27
+ module Completion
28
+ def Completion.candidates(completor_call)
29
+ eval(Client.eval(completor_call))
30
+ rescue Exception # Explicitly rescue Exception to catch eval errors.
31
+ end
32
+
33
+ def Completion.setup
34
+ Readline.completion_proc = lambda do |input|
35
+ candidates("IRB::InputCompletor::CompletionProc.call(#{input.dump})")
36
+ end
37
+ end
38
+ end
39
+
40
+ def self.load_irb
41
+ require 'irb'
42
+
43
+ # Borrowed from Hijack
44
+ const_set 'Workspace', Class.new(IRB::WorkSpace)
45
+ Workspace.class_eval do
46
+ def evaluate(context, statements, file = __FILE__, line = __LINE__)
47
+ if completor_call = statements[/^puts (IRB::InputCompletor.*)/, 1]
48
+ puts Completion.candidates(completor_call)
49
+ elsif statements.strip =~ /^exit/
50
+ exit
51
+ else
52
+ Client.eval(statements)
53
+ end
54
+ end
55
+ end
56
+
57
+ IRB::Context.class_eval do
58
+ def set_last_value value
59
+ @last_value = value
60
+ # Setting the last value variable '_' on the server is
61
+ # pointless. So skip it.
62
+ end
63
+ end
64
+ end
65
+
66
+ def self.start
67
+ load_irb
68
+ ARGV.replace ["--simple-prompt"] if ARGV.empty? # todo
69
+ IRB.setup(nil)
70
+ workspace = Workspace.new
71
+ @CONF = IRB.instance_variable_get(:@CONF)
72
+ @CONF[:INSPECT_MODE] = false
73
+ irb = IRB::Irb.new(workspace)
74
+ Completion.setup
75
+ @CONF[:IRB_RC].call irb.context if @CONF[:IRB_RC]
76
+ @CONF[:MAIN_CONTEXT] = irb.context
77
+ @CONF[:PROMPT_MODE] = :SIMPLE
78
+ trap('SIGINT') { irb.signal_handle }
79
+ catch(:IRB_EXIT) { irb.eval_input }
80
+ end
81
+ end
82
+
83
+ def evaluate code
84
+ # require_relative is missing on MacRuby
85
+ require File.join(File.dirname(__FILE__), '..', 'lib/rum/remote')
86
+ if code and not code.empty?
87
+ if (result = Client.eval(code))
88
+ puts result
89
+ else
90
+ exit 1
91
+ end
92
+ end
93
+ end
94
+
95
+ def switch_to_mri_ruby
96
+ puts "The Rum REPL doesn't yet work with MacIrb. Switching to default Ruby."
97
+ exec('ruby', __FILE__, *ARGV)
98
+ end
99
+
100
+ case not ARGV.empty? and ARGV.first.chomp
101
+ when '-h', '--help'
102
+ puts 'Usage:
103
+ -i, --interactive start a Rum IRB session
104
+ -e, --evaluate CODE evaluate CODE
105
+ CODE evaluate CODE
106
+
107
+ Evaluates code from standard input if arguments are omitted.
108
+
109
+ You can set the environment variable RUM_PORT to change the
110
+ port that is used by Rum-Client and Rum-Server.'
111
+
112
+ when '-i', '--interactive'
113
+ switch_to_mri_ruby if RUBY_DESCRIPTION =~ /MacRuby/
114
+ require_relative '../lib/rum/remote'
115
+ ARGV.shift
116
+ RemoteIRB.start
117
+ when '-e', '--evaluate'
118
+ ARGV.shift
119
+ evaluate ARGV.join(' ')
120
+ when /\S+/
121
+ evaluate ARGV.join(' ')
122
+ else
123
+ evaluate gets(nil)
124
+ end
@@ -0,0 +1,10 @@
1
+ require 'rum'
2
+
3
+ 'shift f1'.do { Rum.restart }
4
+
5
+ # If you use Emacs
6
+ require 'rum/apps'
7
+ 'shift f2'.do { Emacs.eval '(rum-client)'; Emacs.activate }
8
+
9
+ Rum::Server.start
10
+ Rum.start
@@ -0,0 +1,602 @@
1
+ <html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
2
+ <head>
3
+ <title>Rum</title>
4
+ <meta content='text/html;charset=utf-8' http-equiv='Content-Type' />
5
+ <link href='resources/screen.css' media='screen' rel='stylesheet' type='text/css' />
6
+ <link href='resources/highlight.css' media='screen' rel='stylesheet' type='text/css' />
7
+ </head>
8
+ <body>
9
+ <img id='logo' src='resources/logo.png' />
10
+ <div id='nav'>
11
+ <ul>
12
+ <li>
13
+ <a href='#'>Intro</a>
14
+ </li>
15
+ <li>
16
+ <a href='#installation'>Installation</a>
17
+ </li>
18
+ <li>
19
+ <a href='#coding'>Coding</a>
20
+ </li>
21
+ <li>
22
+ <a href='#example'>Example</a>
23
+ </li>
24
+ <li>
25
+ <a href='#reference'>Reference</a>
26
+ </li>
27
+ <li>
28
+ <a href='#development'>Development</a>
29
+ </li>
30
+ </ul>
31
+ </div>
32
+ <div id='wrapper'>
33
+ <div id='intro'>Rum is a cross-platform Hotkey and Macro utility, built in Ruby.<br />Not yet running on Linux, it’s progressing steadily on the Mac (MacRuby) and is fully supported on Windows.</div>
34
+ <img src='resources/screenshot.png' />
35
+ <div id='screenshot-sub'></div>
36
+ <div id='intro-code'>
37
+ <div id='top'></div>
38
+ <div id='content'>
39
+ <img id='flash' src='resources/flash.png' />
40
+ <div id='sshot-sub'>This snippet powers the above screenshot.</div>
41
+ <div class="highlight"><pre>require <span class="s1">&#39;rum&#39;</span>
42
+
43
+ <span class="no">Rum</span><span class="o">.</span><span class="n">layout</span><span class="o">.</span><span class="n">modifier</span> <span class="s1">&#39;caps&#39;</span>
44
+ <span class="s1">&#39;caps&#39;</span><span class="o">.</span><span class="n">do</span> <span class="s1">&#39;(cmd (tab))&#39;</span>
45
+ <span class="s1">&#39;caps shift&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="n">active_window</span><span class="o">.</span><span class="n">close</span> <span class="p">}</span>
46
+
47
+ require <span class="s1">&#39;rum/apps&#39;</span>
48
+ <span class="s1">&#39;caps h&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s1">&#39;Hello from Rum!&#39;</span> <span class="p">}</span>
49
+ <span class="s1">&#39;caps p&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="no">Photoshop</span><span class="o">.</span><span class="n">activate</span> <span class="p">}</span>
50
+ <span class="s1">&#39;caps down&#39;</span><span class="o">.</span><span class="n">do</span><span class="p">(</span><span class="no">Photoshop</span><span class="p">)</span> <span class="p">{</span> <span class="no">Photoshop</span><span class="o">.</span><span class="n">next_blend_mode</span> <span class="p">}</span>
51
+ <span class="s1">&#39;caps b&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="no">Chrome</span><span class="o">.</span><span class="n">activate_and_focus_address_bar</span> <span class="p">}</span>
52
+ <span class="s1">&#39;caps s&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="no">Emacs</span><span class="o">.</span><span class="n">eval</span> <span class="s1">&#39;(slime-repl)&#39;</span><span class="p">;</span> <span class="no">Emacs</span><span class="o">.</span><span class="n">activate</span> <span class="p">}</span>
53
+ <span class="s1">&#39;caps c&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="no">Clipboard</span><span class="o">.</span><span class="n">append</span> <span class="p">}</span>
54
+ <span class="s1">&#39;ctrl shift h&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> type <span class="s1">&#39;hi&#39;</span> <span class="p">}</span>
55
+ <span class="c1"># Caveat: Some hotkey actions are not yet available on the Mac.</span>
56
+
57
+ <span class="no">Rum</span><span class="o">.</span><span class="n">start</span>
58
+ </pre></div>
59
+
60
+ </div>
61
+ <div id='bottom'></div>
62
+ <div id='intro-code-sub'>Rum configuration files are regular Ruby scripts, like the above.<br /> Running Rum is as easy as calling <span class="code">ruby my_rum_config_file.rb</span> from the command line.<br />(Or <span class="code">macruby -rubygems my_rum_config_file.rb</span> on the Mac.)</div>
63
+ </div>
64
+ <div id='guide'>
65
+ <div id='installation'>
66
+ <a name='installation'>
67
+ <h1>Installation</h1>
68
+ </a>
69
+ <div id='gem'>
70
+ <div id='regulargem'>
71
+ <span class='code'>gem install rum</span>
72
+ </div>
73
+ <div id='macgem'>
74
+ <span class='code'>macgem install rum</span>
75
+ <div>
76
+ </div>
77
+ </div>
78
+ <div class='clear'></div>
79
+ </div>
80
+ <p id='current_version'>
81
+ Current version:
82
+ 0.0.1
83
+ <span id='changelog'>(<a href="https://github.com/nonsequitur/rum/blob/master/CHANGELOG">Changelog</a>)</span>
84
+ </p>
85
+ <div id='platforms'>
86
+ <h3>Supported platforms</h3>
87
+ <ul>
88
+ <li>Mac OS X – MacRuby >=0.10</li>
89
+ <li>
90
+ 32-bit Windows XP/Vista/7 – Ruby >=1.9.1p378.<br />
91
+ </li>
92
+ </ul>
93
+ </div>
94
+ <div id='growl'>
95
+ <h2>Recommended: Growl</h2>
96
+ <ul>
97
+ <li>Get Growl: <a href="http://growl.info/">Mac</a>, <a href="http://www.growlforwindows.com/gfw/">Windows</a></li>
98
+ <li>To use Growl in Rum: Add <span class="code">Gui.use Gui::Growl</span> to your Rum config.</li>
99
+ </ul>
100
+ <div id='growl-explanation'>
101
+ <h3>Why Growl?</h3>
102
+ Notification bubbles are a convenient alternative to focus-stealing message boxes.
103
+ Some higher level Rum methods only work smoothly with Growl-style notifications.
104
+ Currently, Growl is the only notification system supported by Rum.
105
+ </div>
106
+ </div>
107
+ </div>
108
+ <div id='coding'>
109
+ <a name='coding'>
110
+ <h1>Coding in Rum</h1>
111
+ </a>
112
+ Rum encourages an interactive approach to coding and a fast code-and-feedback cycle.
113
+ <h2>Core techniques</h2>
114
+ <ul id='core-techniques'>
115
+ <li>
116
+ <h3>rum-client REPL</h3>
117
+ <p>Add <span class="code">Rum::Server.start</span> to your Rum config.</p>
118
+ <p>Call <span class="code">rum-client -i</span> from the command line to start an IRB-session inside a running Rum instance. IRB Completion is fully supported.</p>
119
+ <p>Nearly all snippets in this guide can be evaluated interactively.</p>
120
+ <p>Set the environment variable <span class="code">RUM_PORT</span> to change the port on which client and server connect.</p>
121
+ <p>
122
+ <h3>rum-client in emacs:</h3>
123
+ <ul>
124
+ <li>Get the latest Inf-Ruby via <a href="http://marmalade-repo.org/packages/inf-ruby">ELPA</a></li>
125
+ <li>
126
+ Add the following to your Emacs config:
127
+ <pre id='inf_ruby_setup'>(add-to-list 'inf-ruby-implementations
128
+ '("rum-client" . "rum-client -i --inf-ruby-mode")
129
+ (defun rum-client ()
130
+ (interactive)
131
+ (inf-ruby "rum-client")))
132
+ </pre>
133
+ </li>
134
+ <li>
135
+ Run <span class="code">M-x rum-client</span>
136
+ </li>
137
+ </ul>
138
+ <div id='auto-completion'>
139
+ <h4>Auto-completion</h4>
140
+ <img id='auto-completion' src='resources/emacs-auto-completion.png' />
141
+ <p>
142
+ Company-Mode features auto-completion for IRB sessions.<br />
143
+ <a href="http://www.emacswiki.org/emacs/InfRubyCompany">See here for installation instructions</a>.
144
+ </p>
145
+ </div>
146
+ </p>
147
+ </li>
148
+ <li>
149
+ <h3>Rum.restart</h3>
150
+ Restarts Rum.
151
+ Bind it to a key, like <span class="code">'shift f1'.do { Rum.restart }</span>
152
+ </li>
153
+ </ul>
154
+ Run Rum with this basic, REPL-enabled setup to get started:
155
+ <div id='basic'><div class="highlight"><pre>require <span class="s1">&#39;rum&#39;</span>
156
+
157
+ <span class="s1">&#39;shift f1&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="no">Rum</span><span class="o">.</span><span class="n">restart</span> <span class="p">}</span>
158
+
159
+ <span class="c1"># If you use Emacs</span>
160
+ require <span class="s1">&#39;rum/apps&#39;</span>
161
+ <span class="s1">&#39;shift f2&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="no">Emacs</span><span class="o">.</span><span class="n">eval</span> <span class="s1">&#39;(rum-client)&#39;</span><span class="p">;</span> <span class="no">Emacs</span><span class="o">.</span><span class="n">activate</span> <span class="p">}</span>
162
+
163
+ <span class="no">Rum</span><span class="o">::</span><span class="no">Server</span><span class="o">.</span><span class="n">start</span>
164
+ <span class="no">Rum</span><span class="o">.</span><span class="n">start</span>
165
+ </pre></div>
166
+ </div>
167
+ <div id='example'>
168
+ <a name='example'>
169
+ <h1>Extended Example</h1>
170
+ </a>
171
+ <div class="highlight"><pre><span class="c1">## A short survey of the main features</span>
172
+ <span class="c1">## This file can be found at rum_dir/doc/example.rb</span>
173
+
174
+ require <span class="s1">&#39;rum&#39;</span>
175
+
176
+ <span class="c1"># 1. Set up additional modifiers that can then</span>
177
+ <span class="c1"># be used in hotkey definitions.</span>
178
+ <span class="c1"># Any key can be a modifier</span>
179
+ <span class="no">Rum</span><span class="o">.</span><span class="n">layout</span><span class="o">.</span><span class="n">modifier</span> <span class="s1">&#39;caps&#39;</span>
180
+ <span class="no">Rum</span><span class="o">.</span><span class="n">layout</span><span class="o">.</span><span class="n">modifier</span> <span class="s1">&#39;escape&#39;</span>
181
+
182
+ <span class="c1"># 2. Hotkey definitions</span>
183
+ <span class="s1">&#39;ctrl a&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s1">&#39;foo&#39;</span> <span class="p">}</span>
184
+ <span class="c1"># Hotkeys may consist solely of modifiers</span>
185
+ <span class="s1">&#39;caps&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s1">&#39;bar&#39;</span> <span class="p">}</span>
186
+ <span class="s1">&#39;caps ctrl&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s1">&#39;bar&#39;</span> <span class="p">}</span>
187
+ <span class="c1"># Hotkey conditions</span>
188
+ <span class="s1">&#39;f1&#39;</span><span class="o">.</span><span class="n">do</span><span class="p">(</span> <span class="nb">lambda</span> <span class="p">{</span> <span class="nb">rand</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="p">}</span> <span class="p">)</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s1">&#39;win!&#39;</span> <span class="p">}</span>
189
+ <span class="c1"># Fuzzy hotkeys, trigger regardless of other modifiers being pressed</span>
190
+ <span class="s1">&#39;* ctrl b&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s1">&#39;hi&#39;</span> <span class="p">}</span>
191
+ <span class="c1"># Translations</span>
192
+ <span class="s1">&#39;* caps j&#39;</span><span class="o">.</span><span class="n">translate</span> <span class="s1">&#39;down&#39;</span>
193
+
194
+ <span class="c1"># 3. Gui</span>
195
+ <span class="n">message</span> <span class="s1">&#39;message&#39;</span>
196
+ <span class="n">read</span> <span class="s1">&#39;hi, how are you?&#39;</span> <span class="c1"># Input box</span>
197
+
198
+ <span class="c1"># 4. Keyboard, send keypresses</span>
199
+ type <span class="s1">&#39;hello&#39;</span>
200
+ type <span class="s1">&#39;(ctrl (shift a))&#39;</span> <span class="c1"># Key combinations</span>
201
+
202
+ <span class="c1"># 5. Help and introspection</span>
203
+ <span class="c1"># Prompts you to enter a hotkey and then jumps to its</span>
204
+ <span class="c1"># definition in your text editor.</span>
205
+ <span class="s1">&#39;shift f2&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="no">Rum</span><span class="o">.</span><span class="n">show_hotkey</span> <span class="p">}</span>
206
+
207
+ <span class="c1"># Asks you to enter an arbitrary hotkey and inserts a hotkey</span>
208
+ <span class="c1"># definition snippet.</span>
209
+ <span class="s1">&#39;shift f3&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="no">Rum</span><span class="o">.</span><span class="n">snippet</span> <span class="p">}</span>
210
+
211
+ <span class="c1"># Restarts Rum.</span>
212
+ <span class="s1">&#39;shift f1&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="no">Rum</span><span class="o">.</span><span class="n">restart</span> <span class="p">}</span>
213
+
214
+
215
+ <span class="c1"># 6. Integrate external features</span>
216
+ <span class="no">Gui</span><span class="o">.</span><span class="n">use</span> <span class="no">Gui</span><span class="o">::</span><span class="no">Growl</span>
217
+
218
+ <span class="c1"># Set up a text-editor for opening files</span>
219
+ require <span class="s1">&#39;rum/apps&#39;</span>
220
+ <span class="no">Gui</span><span class="o">.</span><span class="n">use</span> <span class="no">Textmate</span><span class="p">,</span> <span class="ss">:open_file</span>
221
+ <span class="c1"># Or</span>
222
+ <span class="no">Gui</span><span class="o">.</span><span class="n">use</span> <span class="no">Emacs</span><span class="p">,</span> <span class="ss">:open_file</span>
223
+
224
+ <span class="c1"># 7. Start the server. You can now connect to the</span>
225
+ <span class="c1"># Rum process via rum-client.</span>
226
+ <span class="no">Rum</span><span class="o">::</span><span class="no">Server</span><span class="o">.</span><span class="n">start</span>
227
+
228
+ <span class="c1"># 8. Start rum</span>
229
+ <span class="no">Rum</span><span class="o">.</span><span class="n">start</span>
230
+ </pre></div>
231
+
232
+ </div>
233
+ <a name='reference'>
234
+ <h1>Reference</h1>
235
+ </a>
236
+ <p>
237
+ This section is also available as a Ruby source file and can be
238
+ conveniently viewed in a text editor.<br />
239
+ Call <span class="code">Rum.reference</span> or manually open
240
+ <span class="code">rum_dir/doc/reference.rb</span>.
241
+ </p>
242
+ </div>
243
+ </div>
244
+ <div id='reference_wrapper'><div id="table_of_contents"><h1>Chapters</h1><ul><li><a href="#chapter_1">1. Unicode</a></li><li><a href="#chapter_2">2. Layouts</a></li><li><a href="#chapter_3">2. Hotkeys</a></li><li><a href="#chapter_4">3. Keyboard</a></li><li><a href="#chapter_5">3. Gui</a></li><li><a href="#chapter_6">4. Get selected text</a></li><li><a href="#chapter_7">5. Clipboard</a></li><li><a href="#chapter_8">6. More methods</a></li><li><a href="#chapter_9">6. Rum's threading model</a></li><li><a href="#chapter_10">5. Help, introspection</a></li><li><a href="#chapter_11">5. Restarting, server</a></li><li><a href="#chapter_12">6. Windows</a></li><li><a href="#chapter_13">7. Apps</a></li></ul></div>
245
+ <div class="chapter">
246
+ <a name="chapter_1"><h1>1. Unicode</h1></a>
247
+
248
+ <p>Rum is unicode-compatible. The default encoding is UTF-8.</p>
249
+ </div>
250
+ <div class="chapter">
251
+ <a name="chapter_2"><h1>2. Layouts</h1></a>
252
+
253
+ <p>Keyboard layout changes must take place before any hotkey definitions.<br /><br />Rum starts with a default QWERTY layout</p>
254
+ <pre class="highlight"><span class="no">Rum</span><span class="o">.</span><span class="n">layout</span> <span class="c1">#=&gt; #&lt;Rum::Layout:0xb99634 ... &gt;</span></pre>
255
+ <p>Changing the layout</p>
256
+ <pre class="highlight"><span class="no">Rum</span><span class="o">.</span><span class="n">layout</span> <span class="o">=</span> <span class="no">Layouts</span><span class="o">.</span><span class="n">german</span></pre>
257
+ <p>Listing available layouts</p>
258
+ <pre class="highlight"><span class="no">Layouts</span><span class="o">.</span><span class="n">list</span></pre>
259
+ <h2>Editing a layout</h2>
260
+ <pre class="highlight"><span class="n">layout</span> <span class="o">=</span> <span class="no">Rum</span><span class="o">.</span><span class="n">layout</span></pre>
261
+ <h3>Adding a modifier.</h3>
262
+ <p>Any key can be a modifier.</p>
263
+ <pre class="highlight"><span class="n">layout</span><span class="o">.</span><span class="n">modifier</span> <span class="s1">&#39;escape&#39;</span></pre>
264
+ <h3>Aliasing</h3>
265
+ <pre class="highlight"><span class="n">layout</span><span class="o">.</span><span class="n">alias</span> <span class="s1">&#39;escape&#39;</span><span class="p">,</span> <span class="s1">&#39;esc&#39;</span></pre>
266
+ <p>The original key...</p>
267
+ <pre class="highlight"><span class="n">layout</span><span class="o">[</span><span class="s1">&#39;escape&#39;</span><span class="o">]</span> <span class="c1">#=&gt; #&lt;Key:escape&gt;</span></pre>
268
+ <p>...can now be referenced by the alias</p>
269
+ <pre class="highlight"><span class="n">layout</span><span class="o">[</span><span class="s1">&#39;esc&#39;</span><span class="o">]</span> <span class="c1">#=&gt; #&lt;Key:escape&gt;</span></pre>
270
+ <h3>Renaming</h3>
271
+ <pre class="highlight"><span class="n">layout</span><span class="o">.</span><span class="n">rename</span> <span class="s1">&#39;escape&#39;</span><span class="p">,</span> <span class="s1">&#39;foo&#39;</span>
272
+ <span class="n">layout</span><span class="o">[</span><span class="s1">&#39;foo&#39;</span><span class="o">]</span> <span class="c1">#=&gt; #&lt;Key:foo&gt;</span></pre>
273
+ <h3>Finding out the name of a key</h3>
274
+ <p>All keyboard activity is reported at the terminal.<br />Switch to the Rum terminal window and press a key.</p>
275
+ <h2>Advanced</h2>
276
+ <h3>Adding a key</h3>
277
+ <p>add name, *aliases, id</p>
278
+ <pre class="highlight"><span class="n">layout</span><span class="o">.</span><span class="n">add</span> <span class="s1">&#39;my-key&#39;</span><span class="p">,</span> <span class="mi">125</span>
279
+ <span class="n">layout</span><span class="o">.</span><span class="n">add</span> <span class="s1">&#39;my-other-key&#39;</span><span class="p">,</span> <span class="s1">&#39;my-alias&#39;</span><span class="p">,</span> <span class="mi">126</span></pre>
280
+ <h3>Remapping</h3>
281
+ <p>Maps multiple key ids to a single key.</p>
282
+ <pre class="highlight"><span class="n">layout</span><span class="o">[</span><span class="s1">&#39;lctrl&#39;</span><span class="o">].</span><span class="n">id</span> <span class="c1">#=&gt; 39</span>
283
+ <span class="n">layout</span><span class="o">[</span><span class="mi">39</span><span class="o">]</span> <span class="c1">#=&gt; #&lt;Key:lctrl&gt;</span></pre>
284
+ <p>remap from*, to</p>
285
+ <pre class="highlight"><span class="n">layout</span><span class="o">.</span><span class="n">remap</span> <span class="s1">&#39;lctrl&#39;</span><span class="p">,</span> <span class="s1">&#39;ctrl&#39;</span>
286
+ <span class="n">layout</span><span class="o">[</span><span class="mi">39</span><span class="o">]</span> <span class="c1">#=&gt; #&lt;Key:ctrl&gt;</span></pre>
287
+ <h3>Core modifiers</h3>
288
+ <p>Core modifiers, unlike standard modifiers, are always passed on to the Operating System.<br />Shift, Ctrl, etc. are core modifiers.</p>
289
+ <pre class="highlight"><span class="n">layout</span><span class="o">.</span><span class="n">core_modifier</span> <span class="s1">&#39;escape&#39;</span> <span class="c1"># Sets a core modifier.</span></pre>
290
+ </div>
291
+ <div class="chapter">
292
+ <a name="chapter_3"><h1>2. Hotkeys</h1></a>
293
+
294
+ <h3>The basics</h3>
295
+ <pre class="highlight"><span class="s1">&#39;modifiers hotkey&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="n">action</span> <span class="p">}</span>
296
+ <span class="s1">&#39;ctrl shift w&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="n">active_window</span><span class="o">.</span><span class="n">close</span> <span class="p">}</span>
297
+ <span class="s1">&#39;f1&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> type <span class="s1">&#39;hello&#39;</span> <span class="p">}</span></pre>
298
+ <p>The last statement can be abbreviated:</p>
299
+ <pre class="highlight"><span class="s1">&#39;f1&#39;</span><span class="o">.</span><span class="n">do</span> <span class="s1">&#39;hello&#39;</span></pre>
300
+ <h3>Hotkey conditions</h3>
301
+ <p>Restrict hotkeys to trigger only when certain conditions are met.</p>
302
+ <pre class="highlight"><span class="s1">&#39;hotkey&#39;</span><span class="o">.</span><span class="n">do</span><span class="p">(</span><span class="n">condition</span><span class="p">)</span> <span class="p">{</span> <span class="n">action</span> <span class="p">}</span>
303
+ <span class="s1">&#39;f1&#39;</span><span class="o">.</span><span class="n">do</span><span class="p">(</span> <span class="nb">lambda</span> <span class="p">{</span> <span class="nb">rand</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="p">}</span> <span class="p">)</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s1">&#39;win!&#39;</span> <span class="p">}</span></pre>
304
+ <h3>Fuzzy hotkeys</h3>
305
+ <p>The wildcard '*' forces a hotkey to trigger regardless of other modifiers being pressed.</p>
306
+ <pre class="highlight"><span class="s1">&#39;* shift a&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="n">action</span> <span class="p">}</span> <span class="c1"># would be triggered by &#39;ctrl shift option a&#39;</span></pre>
307
+ <p>Normal, non-fuzzy hotkeys take precedence over fuzzy hotkeys.</p>
308
+ <h3>No-Repeat</h3>
309
+ <p>Don't trigger on repetitive key-down events that are spawned when a key is held down for a certain time:</p>
310
+ <pre class="highlight"><span class="s1">&#39;f1&#39;</span><span class="o">.</span><span class="n">do</span><span class="p">(</span><span class="ss">:no_repeat</span><span class="p">)</span> <span class="p">{</span> <span class="n">action</span> <span class="p">}</span></pre>
311
+ <h3>Modifier hotkeys</h3>
312
+ <p>Hotkeys that consist solely of modifiers.</p>
313
+ <pre class="highlight"><span class="s1">&#39;ctrl&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="n">action</span> <span class="p">}</span>
314
+ <span class="s1">&#39;ctrl shift&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="n">action</span> <span class="p">}</span></pre>
315
+ <p>The modifiers used in modifier-only hotkeys can be part of another hotkey.<br />In this case, modifier hotkeys trigger on key-up and only when no other key has been pressed in the meantime.<br />Otherwise, they trigger instantly.<br /><br />Example, assuming 'caps' is a valid modifier:</p>
316
+ <pre class="highlight"><span class="s1">&#39;caps&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="n">action</span> <span class="p">}</span> <span class="c1"># Hotkey 1) - Triggers on key-down.</span>
317
+ <span class="s1">&#39;caps a&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="n">action</span><span class="p">}</span> <span class="c1"># Hotkey 2) - Conflicting hotkey.</span>
318
+ <span class="c1"># Forces hotkey 1) to now trigger on key-up.</span></pre>
319
+ <h3>Translations</h3>
320
+ <p>Translations allow keys or key combinations to act as another key.</p>
321
+ <pre class="highlight"><span class="s1">&#39;ctrl a&#39;</span><span class="o">.</span><span class="n">translate</span> <span class="s1">&#39;up&#39;</span> <span class="c1"># &#39;up&#39; is pressed as soon as &#39;ctrl a&#39; is pressed.</span>
322
+ <span class="c1"># &#39;up&#39; is released when either &#39;ctrl&#39; or &#39;a&#39; are released.</span></pre>
323
+ <p>Translations are usually combined with fuzzy hotkeys</p>
324
+ <pre class="highlight"><span class="s1">&#39;* ctrl a&#39;</span><span class="o">.</span><span class="n">translate</span> <span class="s1">&#39;up&#39;</span> <span class="c1"># would be triggered by e.g. &#39;ctrl shift a&#39;</span></pre>
325
+ <p>Example: Move the 'up' and 'down' cursor keys to the home row</p>
326
+ <pre class="highlight"><span class="s1">&#39;* caps j&#39;</span><span class="o">.</span><span class="n">translate</span> <span class="s1">&#39;down&#39;</span>
327
+ <span class="s1">&#39;* caps k&#39;</span><span class="o">.</span><span class="n">translate</span> <span class="s1">&#39;up&#39;</span></pre>
328
+ <h3>Unregistering and re-registering hotkeys</h3>
329
+ <p>All methods concerned with registering or unregistering hotkeys return actions that can be, again, registered or unregistered.</p>
330
+ <pre class="highlight"><span class="n">action</span> <span class="o">=</span> <span class="s1">&#39;ctrl a&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="n">do_stuff</span> <span class="p">}</span> <span class="c1">#=&gt; #&lt;Rum::Action...&gt;</span>
331
+ <span class="n">action</span><span class="o">.</span><span class="n">unregister</span> <span class="c1">#=&gt; #&lt;Rum::Action...&gt;</span>
332
+ <span class="n">action</span><span class="o">.</span><span class="n">register</span> <span class="c1">#=&gt; #&lt;Rum::Action...&gt;</span></pre>
333
+ <p>Unregistering the conditionless action of a hotkey</p>
334
+ <pre class="highlight"><span class="n">action</span> <span class="o">=</span> <span class="s1">&#39;ctrl a&#39;</span><span class="o">.</span><span class="n">unregister</span></pre>
335
+ <p>Actions with conditions...</p>
336
+ <pre class="highlight"><span class="s1">&#39;ctrl a&#39;</span><span class="o">.</span><span class="n">do</span><span class="p">(</span><span class="n">condition</span><span class="p">)</span> <span class="p">{</span> <span class="n">do_stuff</span> <span class="p">}</span></pre>
337
+ <p>... can't be unregistered this way</p>
338
+ </div>
339
+ <div class="chapter">
340
+ <a name="chapter_4"><h1>3. Keyboard</h1></a>
341
+
342
+ <h2>Caveat: Not yet available on the Mac.</h2>
343
+ <p>Generates keystrokes.</p>
344
+ <pre class="highlight"><span class="no">Keyboard</span><span class="o">.</span><span class="n">type</span> <span class="s1">&#39;hi&#39;</span></pre>
345
+ <p>The 'Keyboard.' prefix can be omitted.</p>
346
+ <pre class="highlight">type <span class="s1">&#39;hello world&#39;</span></pre>
347
+ <p>Some keys have multi-character names or aliases.<br />Wrap them in parentheses.</p>
348
+ <pre class="highlight">type <span class="s1">&#39;foo(tab)bar&#39;</span></pre>
349
+ <p>Pause for a short while between sending characters.</p>
350
+ <pre class="highlight">type <span class="s1">&#39;hello&#39;</span><span class="p">,</span> <span class="ss">:slow</span></pre>
351
+ <h3>Sending key combinations</h3>
352
+ <p>To send key combinations, enclose multiple keys within parentheses and nest them. (S-expressions!)</p>
353
+ <pre class="highlight">type <span class="s1">&#39;(ctrl (shift hi))&#39;</span> <span class="c1"># sends ctrl-down, shift-down, hi, shift-up, ctrl-up</span></pre>
354
+ <p>Backslash (\) acts as an escape character</p>
355
+ <pre class="highlight">type <span class="s1">&#39;\(&#39;</span> <span class="c1"># sends a (</span></pre>
356
+ <h3>Send string literally, without syntax interpretation</h3>
357
+ <pre class="highlight">type<span class="o">!</span> <span class="s1">&#39;(in brackets)&#39;</span></pre>
358
+ <h3>Translations</h3>
359
+ <p>Some keys are translated into key combinations.</p>
360
+ <pre class="highlight">type <span class="s1">&#39;A&#39;</span> <span class="c1"># sends &#39;(shift a)&#39;</span></pre>
361
+ <p>See Rum.layout.translations</p>
362
+ <h3>Sending single keyboard events</h3>
363
+ <pre class="highlight"><span class="no">System</span><span class="o">.</span><span class="n">keydown</span> <span class="s1">&#39;a&#39;</span>
364
+ <span class="no">System</span><span class="o">.</span><span class="n">keyup</span> <span class="s1">&#39;a&#39;</span></pre>
365
+ <p>In a future release, this might be integrated into the main keyboard syntax, like:</p>
366
+ <pre class="highlight">type <span class="s1">&#39;(keydown a)&#39;</span></pre>
367
+ <h3>Auto-release</h3>
368
+ <p>Pressed core modifiers are released before keyboard input is generated.<br />You can safely do the following:</p>
369
+ <pre class="highlight"><span class="s1">&#39;ctrl a&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> type <span class="s1">&#39;w&#39;</span> <span class="p">}</span> <span class="c1"># &#39;ctrl&#39; gets released before &#39;w&#39; is sent.</span></pre>
370
+ <p>Provide the :blind flag to bypass auto-releasing</p>
371
+ <pre class="highlight"><span class="s1">&#39;ctrl a&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> type <span class="s1">&#39;w&#39;</span><span class="p">,</span> <span class="ss">:blind</span> <span class="p">}</span> <span class="c1"># &#39;ctrl&#39; might still be pressed when &#39;w&#39; is sent.</span></pre>
372
+ <h3>Windows-specific: Extended keys</h3>
373
+ <p>Sends 'alt' with the 'extended' flag set.</p>
374
+ <pre class="highlight">type <span class="s1">&#39;(alt-extended)&#39;</span></pre>
375
+ </div>
376
+ <div class="chapter">
377
+ <a name="chapter_5"><h1>3. Gui</h1></a>
378
+
379
+ <h3>Messages</h3>
380
+ <p>Prints a non-disruptive notification when Growl is enabled, falls back to alert (see below) otherwise</p>
381
+ <pre class="highlight"><span class="n">message</span> <span class="s1">&#39;text&#39;</span>
382
+ <span class="n">message</span> <span class="s1">&#39;text&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span></pre>
383
+ <p>Sticky: Keep the message from fading out after a few seconds</p>
384
+ <pre class="highlight"><span class="n">message</span> <span class="s1">&#39;hello&#39;</span><span class="p">,</span> <span class="ss">:sticky</span></pre>
385
+ <p>Callback: Do something when the user clicked on the message</p>
386
+ <pre class="highlight"><span class="n">message</span><span class="p">(</span><span class="s1">&#39;click me&#39;</span><span class="p">)</span> <span class="p">{</span> <span class="n">message</span> <span class="s1">&#39;clicked!&#39;</span> <span class="p">}</span></pre>
387
+ <h3>Alerts</h3>
388
+ <p>Shows a focus-stealing 'ok, cancel' message box, prompting for a response</p>
389
+ <pre class="highlight"><span class="n">alert</span> <span class="s1">&#39;message&#39;</span> <span class="c1"># returns true or false</span>
390
+ <span class="n">alert</span> <span class="s1">&#39;message&#39;</span><span class="p">,</span> <span class="s1">&#39;title&#39;</span></pre>
391
+ <h3>Input boxes</h3>
392
+ <pre class="highlight"><span class="n">read</span> <span class="c1"># returns the response or an empty string</span>
393
+ <span class="n">read</span> <span class="s1">&#39;hi, how are you?&#39;</span>
394
+ <span class="n">read</span> <span class="n">default</span><span class="p">:</span> <span class="s1">&#39;default input&#39;</span>
395
+ <span class="n">read</span> <span class="s1">&#39;hi, how are you?&#39;</span><span class="p">,</span> <span class="n">default</span><span class="p">:</span> <span class="s1">&#39;splendid&#39;</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="s1">&#39;greeting&#39;</span></pre>
396
+ <h3>Choose from candidates</h3>
397
+ <p>This one should launch a quicksilver-like fuzzy selection Gui.</p>
398
+ <pre class="highlight"><span class="n">choose</span> <span class="s1">&#39;choose one&#39;</span><span class="p">,</span> <span class="o">[</span><span class="s1">&#39;red&#39;</span><span class="p">,</span> <span class="s1">&#39;blue&#39;</span><span class="p">,</span> <span class="s1">&#39;yellow&#39;</span><span class="o">]</span></pre>
399
+ <p>TODO: Currently this is only supported via Emacs/Ido.<br />Falls back to an ugly combobox for non Emacs users.<br />Which selection GUIs are there already on the Mac and on Windows that could be harnessed?<br /><br />TODO: Emacs</p>
400
+ <pre class="highlight"><span class="no">Gui</span><span class="o">.</span><span class="n">use</span> <span class="no">Gui</span><span class="o">::</span><span class="no">EmacsInteraction</span></pre>
401
+ <h3>Open (text) files</h3>
402
+ <pre class="highlight"><span class="n">open_file</span> <span class="n">path</span></pre>
403
+ <p>Using a text editor ...</p>
404
+ <pre class="highlight"><span class="no">Gui</span><span class="o">.</span><span class="n">use</span> <span class="no">Textmate</span><span class="p">,</span> <span class="ss">:open_file</span>
405
+ <span class="no">Gui</span><span class="o">.</span><span class="n">use</span> <span class="no">Emacs</span><span class="p">,</span> <span class="ss">:open_file</span></pre>
406
+ <p>... enables jumping to a specific line</p>
407
+ <pre class="highlight"><span class="n">open_file</span> <span class="s1">&#39;foo.txt&#39;</span><span class="p">,</span> <span class="mi">24</span></pre>
408
+ <p>You may re-define open_file to fit your specific needs.</p>
409
+ <h3>Open URLs</h3>
410
+ <pre class="highlight"><span class="n">browse</span> <span class="s1">&#39;example.com&#39;</span> <span class="c1"># HTTP is implicit, unless another protocol is specified</span></pre>
411
+ <h3>Show directories or files in your file manager</h3>
412
+ <pre class="highlight"><span class="n">goto</span> <span class="s1">&#39;foo&#39;</span></pre>
413
+ <h3>Gui Module</h3>
414
+ <p>The above methods are part of the Gui module and may also be called explicitly:</p>
415
+ <pre class="highlight"><span class="no">Gui</span><span class="o">.</span><span class="n">message</span>
416
+ <span class="no">Gui</span><span class="o">.</span><span class="n">read</span>
417
+ <span class="o">.</span><span class="n">.</span><span class="o">.</span></pre>
418
+ </div>
419
+ <div class="chapter">
420
+ <a name="chapter_6"><h1>4. Get selected text</h1></a>
421
+
422
+ <h2>Caveat: Not yet available on the Mac.</h2>
423
+ <p>Grabs the currently selected text.</p>
424
+ <pre class="highlight"><span class="n">get_selection</span> <span class="c1"># returns the current selection or nil</span></pre>
425
+ </div>
426
+ <div class="chapter">
427
+ <a name="chapter_7"><h1>5. Clipboard</h1></a>
428
+
429
+ <h2>Caveat: Not yet available on the Mac.</h2>
430
+ <p>Retrieves the clipboard contents as text.</p>
431
+ <pre class="highlight"><span class="no">Clipboard</span><span class="o">.</span><span class="n">get</span> <span class="c1"># Always returns a string</span></pre>
432
+ <p>Sets the clipboard.</p>
433
+ <pre class="highlight"><span class="no">Clipboard</span><span class="o">.</span><span class="n">set</span> <span class="s1">&#39;hello&#39;</span></pre>
434
+ <p>Sends a 'copy to clipboard' keyboard shortcut and waits until the clipboard changes.</p>
435
+ <pre class="highlight"><span class="no">Clipboard</span><span class="o">.</span><span class="n">copy</span> <span class="c1"># returns true if successful</span></pre>
436
+ <p>Sends a 'paste' keyboard shortcut.</p>
437
+ <pre class="highlight"><span class="no">Clipboard</span><span class="o">.</span><span class="n">paste</span></pre>
438
+ <p>Append the result of get_selection as a new line to the current clipboard content.</p>
439
+ <pre class="highlight"><span class="no">Clipboard</span><span class="o">.</span><span class="n">get</span> <span class="c1">#=&gt; &quot;foo&quot;</span>
440
+ <span class="no">Clipboard</span><span class="o">.</span><span class="n">append</span>
441
+ <span class="no">Clipboard</span><span class="o">.</span><span class="n">get</span> <span class="c1">#=&gt; &quot;foo\nbar&quot;, assuming &#39;bar&#39; was selected.</span></pre>
442
+ <p>Run a block while preserving the clipboard contents.</p>
443
+ <pre class="highlight"><span class="no">Clipboard</span><span class="o">.</span><span class="n">set</span> <span class="s1">&#39;foo&#39;</span>
444
+ <span class="no">Clipboard</span><span class="o">.</span><span class="n">preserve</span> <span class="p">{</span> <span class="no">Clipboard</span><span class="o">.</span><span class="n">set</span> <span class="s1">&#39;bar&#39;</span> <span class="p">}</span>
445
+ <span class="no">Clipboard</span><span class="o">.</span><span class="n">get</span> <span class="c1">#=&gt; &quot;foo&quot;</span></pre>
446
+ </div>
447
+ <div class="chapter">
448
+ <a name="chapter_8"><h1>6. More methods</h1></a>
449
+
450
+ <h3>Waiting</h3>
451
+ <p>Wait until condition is true. Times out after 5 seconds, updates every 0.01 seconds.</p>
452
+ <pre class="highlight"><span class="n">wait</span> <span class="p">{</span> <span class="n">condition</span> <span class="p">}</span> <span class="c1">#=&gt; False when timed-out. Otherwise: true</span></pre>
453
+ <p>Set a 10 second timeout and a 0.5 second update interval.</p>
454
+ <pre class="highlight"><span class="n">wait</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">0</span><span class="o">.</span><span class="mi">5</span><span class="p">)</span> <span class="p">{</span> <span class="n">my_window</span><span class="o">.</span><span class="n">active?</span> <span class="p">}</span></pre>
455
+ <h3>Run a command in a separate terminal window.</h3>
456
+ <pre class="highlight"><span class="n">spawn_in_terminal</span> <span class="n">command</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span>
457
+ <span class="n">spawn_in_terminal</span> <span class="s1">&#39;ruby&#39;</span><span class="p">,</span> <span class="s1">&#39;-e&#39;</span><span class="p">,</span> <span class="s1">&#39;puts Time.now&#39;</span></pre>
458
+ <p>Close the window if the command exits without errors.</p>
459
+ <pre class="highlight"><span class="n">spawn_in_terminal</span> <span class="s1">&#39;ruby&#39;</span><span class="p">,</span> <span class="s1">&#39;-e&#39;</span><span class="p">,</span> <span class="s1">&#39;puts &quot;Hello!&quot;; sleep 2&#39;</span><span class="p">,</span> <span class="ss">:close_if_successful</span></pre>
460
+ <h3>Open documents, run programs</h3>
461
+ <p>Wraps the 'open' command on the Mac and ShellExecute on Windows.</p>
462
+ <pre class="highlight"><span class="n">start</span> <span class="n">file</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span></pre>
463
+ <h3>Applescript</h3>
464
+ <pre class="highlight"><span class="n">applescript</span> <span class="s1">&#39;tell application &quot;System Events&quot;</span>
465
+ <span class="s1"> activate</span>
466
+ <span class="s1"> display dialog &quot;Hello!&quot;</span>
467
+ <span class="s1"> end tell&#39;</span></pre>
468
+ <p>The last three methods are part of the System module and may be called explicitly:</p>
469
+ <pre class="highlight"><span class="no">System</span><span class="o">.</span><span class="n">spawn_in_terminal</span>
470
+ <span class="no">System</span><span class="o">.</span><span class="n">start</span>
471
+ <span class="no">System</span><span class="o">.</span><span class="n">applescript</span></pre>
472
+ </div>
473
+ <div class="chapter">
474
+ <a name="chapter_9"><h1>6. Rum's threading model</h1></a>
475
+
476
+ <p>Rum employs one worker thread that executes all hotkey actions sequentially.<br />Errors during execution are automatically reported via Gui.message.<br /><br />If you have a long running action that may run in parallel with other actions call 'Rum.switch_worker_thread'. Action execution is then resumed on another thread.</p>
477
+ <pre class="highlight"><span class="s1">&#39;ctrl a&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="no">Rum</span><span class="o">.</span><span class="n">switch_worker_thread</span><span class="p">;</span> <span class="n">long_running_stuff</span> <span class="p">}</span></pre>
478
+ <p>The following is also possible...</p>
479
+ <pre class="highlight"><span class="s1">&#39;ctrl a&#39;</span><span class="o">.</span><span class="n">do</span> <span class="p">{</span> <span class="no">Thread</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> <span class="n">long_running_stuff</span> <span class="p">}</span> <span class="p">}</span></pre>
480
+ <p>... but errors in 'long_running_stuff' won't be implicitly caught and reported by Rum.<br /><br />When you call Gui.read, Gui.alert or Gui.print then Rum.switch_worker_thread is automatically run.</p>
481
+ </div>
482
+ <div class="chapter">
483
+ <a name="chapter_10"><h1>5. Help, introspection</h1></a>
484
+
485
+ <p>Prompts you to enter a hotkey and then jumps to its definition via Gui.open_file.</p>
486
+ <pre class="highlight"><span class="no">Rum</span><span class="o">.</span><span class="n">show_hotkey</span></pre>
487
+ <p>(Requires you to register your text-editor, see Gui.open_file above.)<br /><br />Asks you to enter an arbitrary hotkey and inserts a hotkey definition snippet via Keyboard.type.<br />When 'shift a' is pressed, 'shift a'.do { } is inserted.</p>
488
+ <pre class="highlight"><span class="no">Rum</span><span class="o">.</span><span class="n">snippet</span></pre>
489
+ <p>Reads a hotkey and passes it to the block.<br />(Internally used by Rum.snippet)</p>
490
+ <pre class="highlight"><span class="no">Rum</span><span class="o">.</span><span class="n">read_key</span> <span class="p">{</span> <span class="o">|</span><span class="n">hotkey</span><span class="o">|</span> <span class="n">do_stuff_with</span> <span class="n">hotkey</span> <span class="p">}</span></pre>
491
+ <p>Shows information about windows as they become active.</p>
492
+ <pre class="highlight"><span class="no">WindowInfo</span><span class="o">.</span><span class="n">start</span></pre>
493
+ <p>Opens this reference in a text editor</p>
494
+ <pre class="highlight"><span class="no">Rum</span><span class="o">.</span><span class="n">reference</span></pre>
495
+ </div>
496
+ <div class="chapter">
497
+ <a name="chapter_11"><h1>5. Restarting, server</h1></a>
498
+
499
+ <p>Restart the current Rum configuration.</p>
500
+ <pre class="highlight"><span class="no">Rum</span><span class="o">.</span><span class="n">restart</span></pre>
501
+ <p>Start the server. This allows for connections to the Rum process via rum-client.</p>
502
+ <pre class="highlight"><span class="no">Rum</span><span class="o">::</span><span class="no">Server</span><span class="o">.</span><span class="n">start</span></pre>
503
+ </div>
504
+ <div class="chapter">
505
+ <a name="chapter_12"><h1>6. Windows</h1></a>
506
+
507
+ <h2>Caveat: Not yet available on the Mac.</h2>
508
+ <h3>Retrieving windows</h3>
509
+ <pre class="highlight"><span class="n">active_window</span> <span class="c1">#=&gt; #&lt;Rum::System::Window...&gt;</span></pre>
510
+ <p>Traversing all active windows:</p>
511
+ <pre class="highlight"><span class="n">active_windows</span> <span class="c1">#=&gt; #&lt;Enumerator:...&gt;</span>
512
+ <span class="n">active_windows</span><span class="o">.</span><span class="n">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">window</span><span class="o">|</span> <span class="n">window</span><span class="o">.</span><span class="n">close</span> <span class="k">if</span> <span class="n">window</span><span class="o">.</span><span class="n">title</span><span class="o">.</span><span class="n">empty?</span> <span class="p">}</span>
513
+ <span class="n">active_windows</span><span class="o">.</span><span class="n">map</span> <span class="o">&amp;</span><span class="ss">:title</span></pre>
514
+ <h3>Window Matchers</h3>
515
+ <p>WindowMatchers serve as a shorthand for using active_windows.find:</p>
516
+ <pre class="highlight"><span class="n">matcher</span> <span class="o">=</span> <span class="no">Window</span><span class="o">[</span><span class="n">title</span><span class="p">:</span><span class="sr"> /ruby/</span><span class="p">,</span> <span class="n">class_name</span><span class="p">:</span> <span class="s1">&#39;MozillaUIWindowClass&#39;</span><span class="o">]</span></pre>
517
+ <p>or shorter:</p>
518
+ <pre class="highlight"><span class="n">matcher</span> <span class="o">=</span> <span class="no">Window</span><span class="o">[/</span><span class="n">ruby</span><span class="o">/</span><span class="p">,</span> <span class="s1">&#39;MozillaUIWindowClass&#39;</span><span class="o">]</span>
519
+ <span class="n">matcher</span> <span class="c1">#=&gt; #&lt;Rum::System::WindowMatcher...&gt;</span>
520
+ <span class="n">matcher</span><span class="o">.</span><span class="n">find</span> <span class="c1">#=&gt; #&lt;Rum::System::Window...&gt;</span>
521
+ <span class="no">Window</span><span class="o">[</span><span class="n">class_name</span><span class="p">:</span> <span class="s1">&#39;Emacs&#39;</span><span class="o">].</span><span class="n">find</span></pre>
522
+ <p>The first matching window is returned.<br />WindowMatcher attributes differ between platforms.<br />The Windows version shown here supports 'title' and 'class_name'.<br />String arguments are checked for equality with the corresponding window attributes, Regex arguments require a match.</p>
523
+ <h3>Window objects</h3>
524
+ <pre class="highlight"><span class="n">w</span> <span class="o">=</span> <span class="n">active_window</span> <span class="c1">#=&gt; #&lt;Rum::System::Window:...&gt;</span>
525
+ <span class="n">w</span> <span class="o">==</span> <span class="n">active_window</span> <span class="c1">#=&gt; true</span>
526
+ <span class="n">w</span><span class="o">.</span><span class="n">show</span> <span class="c1"># returns true if successful</span>
527
+ <span class="n">w</span><span class="o">.</span><span class="n">minimize</span>
528
+ <span class="n">w</span><span class="o">.</span><span class="n">maximize</span>
529
+ <span class="n">w</span><span class="o">.</span><span class="n">toggle_always_on_top</span>
530
+ <span class="n">w</span><span class="o">.</span><span class="n">title</span> <span class="c1">#=&gt; &quot;A window title&quot;</span>
531
+ <span class="n">w</span><span class="o">.</span><span class="n">class_name</span> <span class="c1">#=&gt; &quot;Chrome_WidgetWin_0&quot;</span>
532
+ <span class="n">w</span><span class="o">.</span><span class="n">close</span>
533
+ <span class="n">w</span><span class="o">.</span><span class="n">kill_task</span> <span class="c1"># kills the task associated with the window</span></pre>
534
+ </div>
535
+ <div class="chapter">
536
+ <a name="chapter_13"><h1>7. Apps</h1></a>
537
+
538
+ <p>Integrates prominent applications into Rum.</p>
539
+ <pre class="highlight">require <span class="s1">&#39;rum/apps&#39;</span></pre>
540
+ <h3>App objects</h3>
541
+ <pre class="highlight"><span class="n">app</span> <span class="o">=</span> <span class="no">Emacs</span> <span class="c1">#=&gt; #&lt;Rum::App:...&gt;</span></pre>
542
+ <p>Start app or bring it to the front when it's already running.<br />This works for all apps.<br />Returns true when the app could be activated instantly.</p>
543
+ <pre class="highlight"><span class="n">app</span><span class="o">.</span><span class="n">activate</span> <span class="c1">#=&gt; true</span></pre>
544
+ <h3>Emacs</h3>
545
+ <pre class="highlight"><span class="no">Emacs</span><span class="o">.</span><span class="n">eval</span> <span class="s1">&#39;(message &quot;hi&quot;)&#39;</span> <span class="c1">#=&gt; &quot;\&quot;hi\&quot;&quot;</span>
546
+ <span class="no">Emacs</span><span class="o">.</span><span class="n">eval</span> <span class="s1">&#39;(* 3 3)&#39;</span> <span class="c1">#=&gt; &quot;9&quot;</span></pre>
547
+ <p>Eval in the current buffer context.</p>
548
+ <pre class="highlight"><span class="no">Emacs</span><span class="o">.</span><span class="n">eval_in_user_buffer</span> <span class="o">=</span> <span class="kp">true</span>
549
+ <span class="no">Emacs</span><span class="o">.</span><span class="n">eval</span> <span class="s1">&#39;default-directory&#39;</span> <span class="c1">#=&gt; &quot;~/current_buffer_dir/&quot;</span>
550
+ <span class="no">Emacs</span><span class="o">.</span><span class="n">eval</span> <span class="s1">&#39;(idle-highlight-mode t)&#39;</span> <span class="c1"># Turns on a minor mode in the current buffer.</span></pre>
551
+ <p>Set this on Windows to allow Emacs.activate to start Emacs when it's not running.</p>
552
+ <pre class="highlight"><span class="no">Emacs</span><span class="o">.</span><span class="n">path</span> <span class="o">=</span> <span class="s1">&#39;path/to/runemacs&#39;</span></pre>
553
+ </div>
554
+ </div>
555
+ <div id='development'>
556
+ <a name='development'>
557
+ <h1>Development</h1>
558
+ </a>
559
+ <p>
560
+ Patches and suggestions are most appreciated.
561
+ </p>
562
+ <p>
563
+ There's a <a href="https://github.com/nonsequitur/rum-dev/blob/master/rum-development.org">low-ceremony
564
+ to-do list</a> to coordinate the development
565
+ of larger-scale features.<br />
566
+ Feel free to have a look if you're interested in contributing.
567
+ </p>
568
+ <h2>Building</h2>
569
+ <p>
570
+ <span class='code'>rake build</span>
571
+ builds the extension and the document.
572
+ </p>
573
+ <p>
574
+ <span class='code'>rake ext</span>
575
+ builds just the extension.
576
+ </p>
577
+ <p>
578
+ <span class='code'>rake doc</span>
579
+ builds this document. Requires Pygments.
580
+ </p>
581
+ <h3>Mac specifics:</h3>
582
+ <p>
583
+ XCode required.
584
+ </p>
585
+ <h3>Windows specifics:</h3>
586
+ <p>
587
+ Visual Studio required. (Out-of-the-box MinGW support coming soon.)
588
+ </p>
589
+ <p>
590
+ You need to setup the Visual Studio build environment before running the rake commands.<br />Call <span class="code">"%programfiles%\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86</span> from your Windows terminal.
591
+ </p>
592
+ <p>
593
+ You might have to delete the following lines from <span class="code">ruby_dir/include/ruby-1.9.x/i386-mswin32/ruby/config.h</span> to work around a compiler error:
594
+ <pre>#if _MSC_VER != 1200
595
+ #error MSC version unmatch: _MSC_VER: 1200 is expected.
596
+ #endif</pre>
597
+ </p>
598
+ <div id='footer'></div>
599
+ </div>
600
+ </div>
601
+ </body>
602
+ </html>