rum 0.0.1-universal-darwin-10 → 0.0.3-universal-darwin-10

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