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
@@ -32,7 +32,7 @@ type '(ctrl (shift a))' # Key combinations
32
32
  # 5. Help and introspection
33
33
  # Prompts you to enter a hotkey and then jumps to its
34
34
  # definition in your text editor.
35
- 'shift f2'.do { Rum.show_hotkey }
35
+ 'shift f2'.do { Rum.visit_hotkey }
36
36
 
37
37
  # Asks you to enter an arbitrary hotkey and inserts a hotkey
38
38
  # definition snippet.
@@ -33,7 +33,7 @@ layout['foo'] #=> #<Key:foo>
33
33
 
34
34
  ## Finding out the name of a key
35
35
  # All keyboard activity is reported at the terminal.
36
- # Switch to the Rum terminal window and press a key.
36
+ # Switch to the Rum terminal window and press a key.
37
37
 
38
38
 
39
39
  ### Advanced
@@ -58,7 +58,7 @@ layout.core_modifier 'escape' # Sets a core modifier.
58
58
 
59
59
 
60
60
 
61
- #### 2. Hotkeys
61
+ #### 3. Hotkeys
62
62
  ## The basics
63
63
  'modifiers hotkey'.do { action }
64
64
  'ctrl shift w'.do { active_window.close }
@@ -129,7 +129,7 @@ action = 'ctrl a'.unregister
129
129
 
130
130
 
131
131
 
132
- #### 3. Keyboard
132
+ #### 4. Keyboard
133
133
 
134
134
  ### Caveat: Not yet available on the Mac.
135
135
 
@@ -177,6 +177,9 @@ type '(keydown a)'
177
177
  # Provide the :blind flag to bypass auto-releasing
178
178
  'ctrl a'.do { type 'w', :blind } # 'ctrl' might still be pressed when 'w' is sent.
179
179
 
180
+ ## Windows-specific: Unicode input
181
+ # Sends unicode input. Supports the key combination syntax from 'type'.
182
+ type_unicode '۩—↑ (ctrl ۞)'
180
183
 
181
184
  ## Windows-specific: Extended keys
182
185
  # Sends 'alt' with the 'extended' flag set.
@@ -184,7 +187,7 @@ type '(alt-extended)'
184
187
 
185
188
 
186
189
 
187
- #### 3. Gui
190
+ #### 5. Gui
188
191
  ## Messages
189
192
  # Prints a non-disruptive notification when Growl is enabled,
190
193
  # falls back to alert (see below) otherwise
@@ -239,13 +242,13 @@ Gui.read
239
242
  ...
240
243
 
241
244
 
242
- #### 4. Get selected text
245
+ #### 6. Get selected text
243
246
  ### Caveat: Not yet available on the Mac.
244
247
  # Grabs the currently selected text.
245
248
  get_selection # returns the current selection or nil
246
249
 
247
250
 
248
- #### 5. Clipboard
251
+ #### 7. Clipboard
249
252
  ### Caveat: Not yet available on the Mac.
250
253
  # Retrieves the clipboard contents as text.
251
254
  Clipboard.get # Always returns a string
@@ -272,7 +275,7 @@ Clipboard.preserve { Clipboard.set 'bar' }
272
275
  Clipboard.get #=> "foo"
273
276
 
274
277
 
275
- #### 6. More methods
278
+ #### 8. More methods
276
279
  ## Waiting
277
280
  # Wait until condition is true. Times out after 5 seconds, updates every 0.01 seconds.
278
281
  wait { condition } #=> False when timed-out. Otherwise: true
@@ -302,14 +305,14 @@ System.spawn_in_terminal
302
305
  System.start
303
306
  System.applescript
304
307
 
305
- #### 6. Rum's threading model
308
+ #### 9. Rum's threading model
306
309
  # Rum employs one worker thread that executes all hotkey actions
307
310
  # sequentially.
308
311
  # Errors during execution are automatically reported via Gui.message.
309
312
 
310
313
  # If you have a long running action that may run in parallel with
311
314
  # other actions call 'Rum.switch_worker_thread'. Action execution is
312
- # then resumed on another thread.
315
+ # then resumed in another thread.
313
316
  'ctrl a'.do { Rum.switch_worker_thread; long_running_stuff }
314
317
 
315
318
  # The following is also possible...
@@ -320,10 +323,10 @@ System.applescript
320
323
  # When you call Gui.read, Gui.alert or Gui.print
321
324
  # then Rum.switch_worker_thread is automatically run.
322
325
 
323
- #### 5. Help, introspection
326
+ #### 10. Help, introspection
324
327
  # Prompts you to enter a hotkey and then jumps to its
325
328
  # definition via Gui.open_file.
326
- Rum.show_hotkey
329
+ Rum.visit_hotkey
327
330
  # (Requires you to register your text-editor, see Gui.open_file above.)
328
331
 
329
332
  # Asks you to enter an arbitrary hotkey and inserts a hotkey
@@ -342,16 +345,16 @@ WindowInfo.start
342
345
  Rum.reference
343
346
 
344
347
 
345
- #### 5. Restarting, server
348
+ #### 11. Restarting, server
346
349
  # Restart the current Rum configuration.
347
- Rum.restart
350
+ Rum.restart
348
351
 
349
352
  # Start the server. This allows for connections to the
350
353
  # Rum process via rum-client.
351
354
  Rum::Server.start
352
355
 
353
356
 
354
- #### 6. Windows
357
+ #### 12. Windows
355
358
 
356
359
  ### Caveat: Not yet available on the Mac.
357
360
 
@@ -388,8 +391,19 @@ w.class_name #=> "Chrome_WidgetWin_0"
388
391
  w.close
389
392
  w.kill_task # kills the task associated with the window
390
393
 
394
+ ## Child windows
395
+ # Enumerate all child windows
396
+ w = active_window
397
+ w.child_windows { |child| puts child.class_name }
398
+ w.child_windows # => #<Enumerator: ...>
391
399
 
392
- #### 7. Apps
400
+ # Get child window by class name. Pattern can be a regex or a string (for exact matches).
401
+ w.child_window(pattern)
402
+
403
+ # Example: Activate Evernote's search field
404
+ Evernote.window.child_window('ENAutoCompleteEditCtrl').show
405
+
406
+ #### 13. Apps
393
407
  # Integrates prominent applications into Rum.
394
408
  require 'rum/apps'
395
409
 
@@ -412,4 +426,3 @@ Emacs.eval '(idle-highlight-mode t)' # Turns on a minor mode in the current buff
412
426
  # Set this on Windows to allow Emacs.activate
413
427
  # to start Emacs when it's not running.
414
428
  Emacs.path = 'path/to/runemacs'
415
-
@@ -1,14 +1,17 @@
1
1
  require 'haml'
2
2
 
3
+ Encoding.default_external = Encoding::UTF_8
4
+
3
5
  class Doc
4
6
  module Pygmentize
5
7
  Bin = if RUBY_PLATFORM =~ /mswin|mingw/ and ENV['USER'] == 'nonsequitur'
6
- 'C:/Programme/Python26/Scripts/pygmentize.exe'
8
+ python_dir = File.expand_path('~/vendor/Python32')
9
+ "#{python_dir}/python.exe #{python_dir}/scripts/pygmentize"
7
10
  else
8
11
  'pygmentize'
9
12
  end
10
- Cmd = "#{Bin} -O encoding=utf-8 -l ruby -f html"
11
-
13
+ Cmd = "#{Bin} -l ruby -f html"
14
+
12
15
  def self.file file
13
16
  fix_pygments_output(`#{Cmd} #{file}`)
14
17
  end
@@ -22,9 +25,8 @@ class Doc
22
25
  end
23
26
 
24
27
  def self.fix_pygments_output str
25
- # Bug in Pygments 1.3.1: 'type' is no Ruby builtin
26
- str.gsub('<span class="nb">type</span>', 'type')\
27
- .gsub('<span class="nb">require</span>', 'require')
28
+ # Don't highlight 'require'
29
+ str.gsub('<span class="nb">require</span>', 'require')
28
30
  end
29
31
 
30
32
  class Snippets
@@ -63,7 +65,7 @@ class Doc
63
65
  parse
64
66
  to_html
65
67
  end
66
-
68
+
67
69
  def parse
68
70
  @result = []
69
71
  @last_type = nil
@@ -81,7 +83,7 @@ class Doc
81
83
  else [:code, line]
82
84
  end
83
85
  end
84
-
86
+
85
87
  EmptyAllowed = { code: true, text: true }
86
88
 
87
89
  def compose_doc type, line
@@ -97,7 +99,7 @@ class Doc
97
99
 
98
100
  class TableOfContents
99
101
  Heading = Struct.new(:text, :anchor_name)
100
-
102
+
101
103
  def initialize
102
104
  @headings = []
103
105
  end
@@ -106,7 +108,7 @@ class Doc
106
108
  chapter_number = @headings.count + 1
107
109
  @headings << Heading.new(heading, "chapter_#{chapter_number}")
108
110
  end
109
-
111
+
110
112
  def heading_html
111
113
  heading = @headings.last
112
114
  "<a name=\"#{heading.anchor_name}\"><h1>#{heading.text}</h1></a>"
@@ -133,7 +135,7 @@ class Doc
133
135
  def to_html
134
136
  snippets = Pygmentize::Snippets.new
135
137
  table_of_contents = TableOfContents.new
136
-
138
+
137
139
  sections = @result.map do |type, *lines|
138
140
  case type
139
141
  when :chapter
@@ -225,7 +227,7 @@ EOF
225
227
  end
226
228
 
227
229
  def save
228
- File.open(@output, 'w') { |f| f.write @doc }
230
+ File.open(@output, 'wb') { |f| f.write @doc }
229
231
  end
230
232
 
231
233
  def build
@@ -6,7 +6,12 @@
6
6
  %link(rel="stylesheet" href="resources/highlight.css" type="text/css" media="screen")
7
7
 
8
8
  %body
9
- %img{id: "logo", src: "resources/logo.png"}
9
+ %a{href: "#"}
10
+ %img{id: "logo", src: "resources/logo.png"}
11
+ %a{href: "https://github.com/nonsequitur/rum"}
12
+ %img{style: "position: absolute; top: 0; right: 0; border: 0;",
13
+ src: "https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png",
14
+ alt:"Fork me on GitHub"}
10
15
  #nav
11
16
  %ul
12
17
  %li
@@ -22,7 +27,7 @@
22
27
  %li
23
28
  %a{href: "#development"} Development
24
29
  #wrapper
25
- #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.
30
+ #intro Rum is a cross-platform Hotkey and Macro utility, built in Ruby.<br />It runs on Windows and Mac OS.
26
31
 
27
32
  %img{src: "resources/screenshot.png"}
28
33
  #screenshot-sub
@@ -56,7 +61,7 @@
56
61
  #platforms
57
62
  %h3 Supported platforms
58
63
  %ul
59
- %li Mac OS X – MacRuby >=0.10
64
+ %li Mac OS X >= 10.7 – MacRuby >=0.10.<br />
60
65
  %li
61
66
  32-bit Windows XP/Vista/7 – Ruby >=1.9.1p378.<br />
62
67
  #growl
@@ -5,7 +5,7 @@
5
5
  id delegate;
6
6
  }
7
7
  -(id)init;
8
- -(Event*)handleEvent:(Event*)event;
8
+ -(Event*)handleKeyEvent:(Event*)event;
9
9
  @end
10
10
 
11
11
  CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *eventTapObject);
@@ -22,18 +22,18 @@ CFMachPortRef keyboard_event_tap;
22
22
  -(id)init {
23
23
  [super init];
24
24
  keyboard_event_tap = CGEventTapCreate(kCGHIDEventTap,
25
- kCGHeadInsertEventTap,
26
- kCGEventTapOptionDefault,
27
- CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventFlagsChanged),
28
- &eventCallback,
29
- self);
25
+ kCGHeadInsertEventTap,
26
+ kCGEventTapOptionDefault,
27
+ CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventFlagsChanged),
28
+ &eventCallback,
29
+ self);
30
30
  CFRunLoopSourceRef tapSource = CFMachPortCreateRunLoopSource(NULL, keyboard_event_tap, 0);
31
31
  CFRunLoopAddSource((CFRunLoopRef) [[NSRunLoop currentRunLoop] getCFRunLoop], tapSource, kCFRunLoopCommonModes);
32
-
32
+
33
33
  return self;
34
34
  }
35
35
 
36
- -(Event*)handleEvent:(Event*)event {
36
+ -(Event*)handleKeyEvent:(Event*)event {
37
37
  // to be overridden by ruby code
38
38
  return event;
39
39
  }
@@ -72,6 +72,6 @@ CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type,
72
72
  default:
73
73
  return event;
74
74
  }
75
-
76
- return [((id) eventTapObject) handleEvent:[[Event alloc] initWithEventRef:event tapProxy:proxy type:type down:is_down]].eventRef;
75
+
76
+ return [((id) eventTapObject) handleKeyEvent:[[Event alloc] initWithEventRef:event tapProxy:proxy type:type down:is_down]].eventRef;
77
77
  }
@@ -3,7 +3,7 @@
3
3
  archiveVersion = 1;
4
4
  classes = {
5
5
  };
6
- objectVersion = 45;
6
+ objectVersion = 46;
7
7
  objects = {
8
8
 
9
9
  /* Begin PBXBuildFile section */
@@ -169,8 +169,12 @@
169
169
  0867D690FE84028FC02AAC07 /* Project object */ = {
170
170
  isa = PBXProject;
171
171
  buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "KeyboardHook" */;
172
- compatibilityVersion = "Xcode 3.1";
172
+ compatibilityVersion = "Xcode 3.2";
173
+ developmentRegion = English;
173
174
  hasScannedForEncodings = 1;
175
+ knownRegions = (
176
+ en,
177
+ );
174
178
  mainGroup = 0867D691FE84028FC02AAC07 /* KeyboardHook */;
175
179
  productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
176
180
  projectDirPath = "";
@@ -220,17 +224,17 @@
220
224
  isa = XCBuildConfiguration;
221
225
  buildSettings = {
222
226
  ALWAYS_SEARCH_USER_PATHS = NO;
227
+ COMBINE_HIDPI_IMAGES = YES;
223
228
  COPY_PHASE_STRIP = NO;
224
229
  DYLIB_COMPATIBILITY_VERSION = 1;
225
230
  DYLIB_CURRENT_VERSION = 1;
226
231
  FRAMEWORK_SEARCH_PATHS = (
227
232
  "$(inherited)",
228
- "\"$(SRCROOT)/../../DDHidLib-1.1/build/Release\"",
229
233
  "\"$(SRCROOT)/..\"",
234
+ /Library/Frameworks,
230
235
  );
231
236
  FRAMEWORK_VERSION = A;
232
237
  GCC_DYNAMIC_NO_PIC = NO;
233
- GCC_ENABLE_FIX_AND_CONTINUE = YES;
234
238
  GCC_MODEL_TUNING = G5;
235
239
  GCC_OPTIMIZATION_LEVEL = 0;
236
240
  GCC_PRECOMPILE_PREFIX_HEADER = YES;
@@ -246,14 +250,15 @@
246
250
  isa = XCBuildConfiguration;
247
251
  buildSettings = {
248
252
  ALWAYS_SEARCH_USER_PATHS = NO;
253
+ COMBINE_HIDPI_IMAGES = YES;
249
254
  DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
250
255
  DYLIB_COMPATIBILITY_VERSION = 1;
251
256
  DYLIB_CURRENT_VERSION = 1;
252
257
  EXECUTABLE_EXTENSION = bundle;
253
258
  FRAMEWORK_SEARCH_PATHS = (
254
259
  "$(inherited)",
255
- "\"$(SRCROOT)/../../DDHidLib-1.1/build/Release\"",
256
260
  "\"$(SRCROOT)/..\"",
261
+ /Library/Frameworks,
257
262
  );
258
263
  FRAMEWORK_VERSION = A;
259
264
  GCC_ENABLE_OBJC_GC = supported;
@@ -277,8 +282,7 @@
277
282
  GCC_WARN_ABOUT_RETURN_TYPE = YES;
278
283
  GCC_WARN_UNUSED_VARIABLE = YES;
279
284
  ONLY_ACTIVE_ARCH = YES;
280
- PREBINDING = NO;
281
- SDKROOT = macosx10.5;
285
+ SDKROOT = macosx10.7;
282
286
  };
283
287
  name = Debug;
284
288
  };
@@ -291,8 +295,7 @@
291
295
  GCC_WARN_ABOUT_RETURN_TYPE = YES;
292
296
  GCC_WARN_UNUSED_VARIABLE = YES;
293
297
  ONLY_ACTIVE_ARCH = YES;
294
- PREBINDING = NO;
295
- SDKROOT = macosx10.5;
298
+ SDKROOT = macosx10.7;
296
299
  };
297
300
  name = Release;
298
301
  };
@@ -22,7 +22,7 @@ static BOOL pass_key_event_to_ruby(struct KeyEvent *key_event) {
22
22
  INT2NUM(key_event->scancode),
23
23
  (key_event->down ? Qtrue : Qfalse) };
24
24
  VALUE event = rb_class_new_instance(3, event_attributes, cEvent);
25
-
25
+
26
26
  return (Qtrue == rb_funcall(ruby_callback_proc, id_call, 1, event));
27
27
  }
28
28
 
@@ -36,7 +36,7 @@ callback_function(int Code, WPARAM wParam, LPARAM lParam)
36
36
  #ifdef DEBUG
37
37
  puts("Enter Callback");
38
38
  #endif
39
-
39
+
40
40
  key_event.vkcode = kbd->vkCode;
41
41
  key_event.scancode = kbd->scanCode;
42
42
  key_event.down = (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN);
@@ -96,7 +96,7 @@ static VALUE start(int argc, VALUE* argv, VALUE self)
96
96
  HMODULE module = GetModuleHandle(NULL);
97
97
  thread = GetCurrentThreadId();
98
98
  rb_scan_args(argc, argv, "0&", &ruby_callback_proc);
99
-
99
+
100
100
  keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)callback_function,
101
101
  module, 0);
102
102
  rb_thread_blocking_region(pump_messages, 0, 0, 0);
@@ -1,10 +1,15 @@
1
1
  #include <windows.h>
2
2
 
3
- DWORD g_MainThreadID;
3
+ static DWORD g_MainThreadID;
4
4
 
5
5
  void autohotkey_stuff_initialize(DWORD main_thread_id)
6
6
  {
7
- g_MainThreadID = main_thread_id;
7
+ g_MainThreadID = main_thread_id;
8
+ }
9
+
10
+ static void key_down_up(BYTE vkcode) {
11
+ keybd_event(vkcode, 0, 0, 0);
12
+ keybd_event(vkcode, 0, KEYEVENTF_KEYUP, 0);
8
13
  }
9
14
 
10
15
  HWND AttemptSetForeground(HWND aTargetWindow, HWND aForeWindow)
@@ -80,9 +85,9 @@ HWND SetForegroundWindowEx(HWND aTargetWindow)
80
85
  else
81
86
  show_mode = SW_SHOW;
82
87
  ShowWindow(aTargetWindow, show_mode);
83
-
84
-
85
-
88
+
89
+
90
+
86
91
  // if (g_os.IsWin95() || (!g_os.IsWin9x() && !g_os.IsWin2000orLater()))) // Win95 or NT
87
92
  // Try a simple approach first for these two OS's, since they don't have
88
93
  // any restrictions on focus stealing:
@@ -199,10 +204,8 @@ HWND SetForegroundWindowEx(HWND aTargetWindow)
199
204
  // but later, after the hotkey is released, it can be. So perhaps this is being
200
205
  // caused by the fact that the user has keys held down (logically or physically?)
201
206
  // Releasing those keys with a key-up event might help, so try that sometime:
202
- /* Remarks from Rum: The following two lines are disabled since KeyEvent
203
- is not implemented: */
204
- /* KeyEvent(KEYDOWNANDUP, VK_MENU); */
205
- /* KeyEvent(KEYDOWNANDUP, VK_MENU); */
207
+ key_down_up(VK_LMENU);
208
+ key_down_up(VK_LMENU);
206
209
  //KeyEvent(KEYDOWN, VK_LWIN) ;
207
210
  //KeyEvent(KEYDOWN, VK_TAB) ;
208
211
  //KeyEvent(KEYUP, VK_TAB) ;
@@ -252,4 +255,3 @@ HWND SetForegroundWindowEx(HWND aTargetWindow)
252
255
  else
253
256
  return NULL ;
254
257
  }
255
-