karabiner 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rspec +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +122 -0
- data/Rakefile +7 -0
- data/bin/karabiner +8 -0
- data/bin/karabiner-dsl +11 -0
- data/dotremap.gemspec +26 -0
- data/img/disabled.png +0 -0
- data/img/enabled.png +0 -0
- data/lib/karabiner/appdef.rb +23 -0
- data/lib/karabiner/cli.rb +25 -0
- data/lib/karabiner/config.rb +15 -0
- data/lib/karabiner/dsl/group.rb +10 -0
- data/lib/karabiner/dsl/item.rb +38 -0
- data/lib/karabiner/dsl/root.rb +28 -0
- data/lib/karabiner/group.rb +16 -0
- data/lib/karabiner/invoke_history.rb +16 -0
- data/lib/karabiner/item.rb +54 -0
- data/lib/karabiner/key.rb +85 -0
- data/lib/karabiner/namespace.rb +5 -0
- data/lib/karabiner/property.rb +15 -0
- data/lib/karabiner/remap.rb +16 -0
- data/lib/karabiner/root.rb +30 -0
- data/lib/karabiner/version.rb +3 -0
- data/lib/karabiner/vkopenurldef.rb +11 -0
- data/lib/karabiner/xml_tree.rb +42 -0
- data/lib/karabiner.rb +56 -0
- data/spec/lib/dotremap/appdef_spec.rb +35 -0
- data/spec/lib/dotremap/karabiner_spec.rb +29 -0
- data/spec/lib/dotremap/key_spec.rb +113 -0
- data/spec/lib/dotremap/remap_spec.rb +10 -0
- data/spec/lib/dotremap_spec.rb +335 -0
- data/spec/spec_helper.rb +2 -0
- metadata +158 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 54eca927143367b5272357cf58664363593c5b9b
|
4
|
+
data.tar.gz: 0bdcaaaee69fa945cab5e71d29d1b53b890c783f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6d6370cb2fdead72745f722f9948bd5a9014e226cb12959d8aba50ba7f37f302008475f101dcfa1d6a76622d92a66daef78b364ec8a6f3849e772371d2edb59c
|
7
|
+
data.tar.gz: 0004cc00131dec168743bd19b4dd297960d9230fab516f9575e474692050c69af437c53520704fc2ad84f35ddf5bf1ac8523fed260f008ac9b1a6138efadd16c
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-c
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Takashi Kokubun
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
# Karabiner DSL [](https://travis-ci.org/k0kubun/karabiner-dsl)
|
2
|
+
|
3
|
+
Lightweight keyremap configuration DSL for [Karabiner](https://pqrs.org/osx/karabiner/index.html.en)
|
4
|
+
|
5
|
+
## Why Karabiner DSL?
|
6
|
+
|
7
|
+
Original [Karabiner's configuration](https://pqrs.org/osx/karabiner/xml.html.ja) is very hard to write.
|
8
|
+
Karabiner DSL is its wrapper, which is easy-to-write and readable.
|
9
|
+
|
10
|
+
If you write Karabiner's config with Karabiner DSL, you can update your keyremap configuration quickly.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
First of all, you have to install [Karabiner](https://pqrs.org/osx/karabiner/index.html.en).
|
15
|
+
Karabiner is a keyboard remap utility for Mac OSX.
|
16
|
+
|
17
|
+
Then execute:
|
18
|
+
|
19
|
+
```bash
|
20
|
+
$ gem install karabiner
|
21
|
+
```
|
22
|
+
|
23
|
+
Then `karabiner` executable will be installed.
|
24
|
+
This gem provides only `karabiner dsl` subcommand and other subcommands are delegated to original CLI for Karabiner.app.
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
### 1. Create ~/.karabiner
|
28
|
+
|
29
|
+
```rb
|
30
|
+
item "Command+G to open Google Chrome" do
|
31
|
+
remap "Cmd-g", to: invoke("Google Chrome")
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
### 2. Execute karabiner dsl command
|
36
|
+
|
37
|
+
```bash
|
38
|
+
$ karabiner dsl
|
39
|
+
```
|
40
|
+
|
41
|
+
Then `karabiner dsl` will update Karabiner's config as you expected.
|
42
|
+
|
43
|
+

|
44
|
+
|
45
|
+
### 3. Enable your favorite configurations
|
46
|
+
|
47
|
+

|
48
|
+
|
49
|
+
Enjoy!
|
50
|
+
|
51
|
+
## How to write ~/.karabiner
|
52
|
+
### Basics
|
53
|
+
|
54
|
+
karabiner-dsl's DSL is a superset of Ruby.
|
55
|
+
So you can use any Ruby methods in ~/.karabiner.
|
56
|
+
|
57
|
+
#### item
|
58
|
+
|
59
|
+
```rb
|
60
|
+
item "configuration unit" do
|
61
|
+
...
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
In karabiner-dsl, any Karabiner's configuration unit is expressed in `item` and its `do ~ end` block.
|
66
|
+
You can group some remap configurations in one item and enable them in one click.
|
67
|
+
|
68
|
+
#### remap
|
69
|
+
|
70
|
+
```rb
|
71
|
+
item "remap example" do
|
72
|
+
remap "Cmd-a", to: "C-a"
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
If you want to add remap configuration, you have to call `remap` method.
|
77
|
+
In this example, Command+A will be remapped to Control+A.
|
78
|
+
|
79
|
+
You have to write "key expression" to specify keys to remap.
|
80
|
+
|
81
|
+
#### key expression
|
82
|
+
|
83
|
+
- `a`, `A`, `1`, `;`, `tab`, `Tab`, `space`, `up`, `down`
|
84
|
+
- any string without `-` will be regarded as single key
|
85
|
+
- ignore upcase or downcase
|
86
|
+
- `C-a`, `Ctrl-a`
|
87
|
+
- regarded as Control + A
|
88
|
+
- `C-` is a short expression of `Ctrl-`
|
89
|
+
- `M-a`, `Opt-a`
|
90
|
+
- regarded as Option + A
|
91
|
+
- `Shift-a`
|
92
|
+
- regarded as large A
|
93
|
+
- if you write just `A`, it will be regarded as small a
|
94
|
+
- `Cmd-a`
|
95
|
+
- regarded as Command + A
|
96
|
+
- `Cmd-Shift-a`
|
97
|
+
- regarded as Command + Shift + A
|
98
|
+
- you can use any combination of Ctrl, Opt, Shift, Cmd
|
99
|
+
|
100
|
+
#### available single keys
|
101
|
+
|
102
|
+
```
|
103
|
+
a b c ... x y z
|
104
|
+
0 1 2 ... 7 8 9
|
105
|
+
F1 F2 ... F11 F12
|
106
|
+
\ [ ] ; ' , . / - =
|
107
|
+
Up Down Right Left
|
108
|
+
space tab delete forward_delete capslock
|
109
|
+
|
110
|
+
Ctrl_R Ctrl_L
|
111
|
+
Opt_R Opt_L
|
112
|
+
Cmd_R Cmd_L
|
113
|
+
Shift_R Shift_L
|
114
|
+
```
|
115
|
+
|
116
|
+
## Contributing
|
117
|
+
|
118
|
+
1. Fork it ( https://github.com/k0kubun/karabiner-dsl/fork )
|
119
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
120
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
121
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
122
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/karabiner
ADDED
data/bin/karabiner-dsl
ADDED
data/dotremap.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'karabiner/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "karabiner"
|
8
|
+
spec.version = Karabiner::VERSION
|
9
|
+
spec.authors = ["Takashi Kokubun"]
|
10
|
+
spec.email = ["takashikkbn@gmail.com"]
|
11
|
+
spec.summary = %q{Lightweight keyremap configuration DSL}
|
12
|
+
spec.description = %q{Lightweight keyremap configuration DSL for Karabiner}
|
13
|
+
spec.homepage = "https://github.com/k0kubun/karabiner-dsl"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.3.2"
|
23
|
+
spec.add_development_dependency "rspec", "~> 3.0.0"
|
24
|
+
spec.add_development_dependency "pry"
|
25
|
+
spec.add_dependency 'unindent', '~> 1.0'
|
26
|
+
end
|
data/img/disabled.png
ADDED
Binary file
|
data/img/enabled.png
ADDED
Binary file
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "karabiner/xml_tree"
|
2
|
+
|
3
|
+
class Karabiner::Appdef
|
4
|
+
include Karabiner::XmlTree
|
5
|
+
|
6
|
+
AVAILABLE_OPTIONS = %i(
|
7
|
+
equal
|
8
|
+
prefix
|
9
|
+
suffix
|
10
|
+
).freeze
|
11
|
+
|
12
|
+
def initialize(appname, options)
|
13
|
+
property = Karabiner::Property.new("appname", appname)
|
14
|
+
add_child(property)
|
15
|
+
|
16
|
+
options.each do |option, value|
|
17
|
+
raise "Unavailable option: #{property}" unless AVAILABLE_OPTIONS.include?(option)
|
18
|
+
|
19
|
+
property = Karabiner::Property.new(option, value)
|
20
|
+
add_child(property)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "karabiner/namespace"
|
2
|
+
|
3
|
+
module Karabiner::CLI
|
4
|
+
CLI_PATH = "/Applications/Karabiner.app/Contents/Library/bin/karabiner"
|
5
|
+
|
6
|
+
def self.reload_xml
|
7
|
+
system("#{CLI_PATH} reloadxml")
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.current_config
|
11
|
+
changed = `#{CLI_PATH} changed`
|
12
|
+
config_by_changed(changed)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def self.config_by_changed(changed)
|
18
|
+
config = {}
|
19
|
+
changed.each_line do |line|
|
20
|
+
property, value = line.strip.split("=")
|
21
|
+
config[property] = value
|
22
|
+
end
|
23
|
+
config
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "karabiner/namespace"
|
3
|
+
|
4
|
+
class Karabiner::Config
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def_delegator :@parent, :item
|
8
|
+
def_delegator :@parent, :group
|
9
|
+
|
10
|
+
def initialize(name)
|
11
|
+
@name = name
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_writer :parent
|
15
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "karabiner/namespace"
|
2
|
+
require "karabiner/property"
|
3
|
+
require "karabiner/remap"
|
4
|
+
require "karabiner/invoke_history"
|
5
|
+
|
6
|
+
module Karabiner::DSL::Item
|
7
|
+
AVAILABLE_PROPERTIES = %i(
|
8
|
+
name
|
9
|
+
identifier
|
10
|
+
autogen
|
11
|
+
).freeze
|
12
|
+
|
13
|
+
def remap(target, options = {})
|
14
|
+
remap = Karabiner::Remap.new(target, options[:to])
|
15
|
+
add_child(remap)
|
16
|
+
end
|
17
|
+
|
18
|
+
def show_message(message)
|
19
|
+
property = Karabiner::Property.new("autogen", "__ShowStatusMessage__ #{message}")
|
20
|
+
add_child(property)
|
21
|
+
end
|
22
|
+
|
23
|
+
def invoke(application)
|
24
|
+
Karabiner::InvokeHistory.register(application)
|
25
|
+
"VK_OPEN_URL_APP_#{application.gsub(/ /, '_')}"
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def method_missing(property, value = '', options = {})
|
31
|
+
if AVAILABLE_PROPERTIES.include?(property)
|
32
|
+
property = Karabiner::Property.new(property, value, options)
|
33
|
+
add_child(property)
|
34
|
+
else
|
35
|
+
super
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "karabiner/namespace"
|
2
|
+
require "karabiner/appdef"
|
3
|
+
require "karabiner/config"
|
4
|
+
require "karabiner/item"
|
5
|
+
require "karabiner/group"
|
6
|
+
require "karabiner/dsl/group"
|
7
|
+
|
8
|
+
module Karabiner::DSL::Root
|
9
|
+
include Karabiner::DSL::Group
|
10
|
+
|
11
|
+
def group(name, &block)
|
12
|
+
group = Karabiner::Group.new(name)
|
13
|
+
group.instance_exec(&block)
|
14
|
+
add_child(group)
|
15
|
+
end
|
16
|
+
|
17
|
+
def config(name, &block)
|
18
|
+
config = Karabiner::Config.new(name)
|
19
|
+
config.parent = self
|
20
|
+
config.instance_exec(&block)
|
21
|
+
add_config(config)
|
22
|
+
end
|
23
|
+
|
24
|
+
def appdef(appname = '', options = {})
|
25
|
+
appdef = Karabiner::Appdef.new(appname, options)
|
26
|
+
add_child(appdef)
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "karabiner/namespace"
|
3
|
+
require "karabiner/dsl/group"
|
4
|
+
|
5
|
+
class Karabiner::Group
|
6
|
+
extend Forwardable
|
7
|
+
include Karabiner::XmlTree
|
8
|
+
include Karabiner::DSL::Group
|
9
|
+
|
10
|
+
def_delegator :@item, :to_xml
|
11
|
+
def_delegator :@item, :add_child
|
12
|
+
|
13
|
+
def initialize(name)
|
14
|
+
@item = Karabiner::Item.new(name, skip_identifier: true)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "set"
|
2
|
+
require "karabiner/vkopenurldef"
|
3
|
+
|
4
|
+
module Karabiner::InvokeHistory
|
5
|
+
def self.clear_histroy
|
6
|
+
@@registered_applications = Set.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.register(application)
|
10
|
+
registered_applications.add(application)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.registered_applications
|
14
|
+
@@registered_applications ||= Set.new
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "karabiner/dsl/item"
|
2
|
+
require "karabiner/xml_tree"
|
3
|
+
|
4
|
+
class Karabiner::Item
|
5
|
+
include Karabiner::XmlTree
|
6
|
+
include Karabiner::DSL::Item
|
7
|
+
|
8
|
+
AVAILABLE_OPTIONS = %i(
|
9
|
+
not
|
10
|
+
only
|
11
|
+
config_not
|
12
|
+
config_only
|
13
|
+
).freeze
|
14
|
+
|
15
|
+
def initialize(name, options = {})
|
16
|
+
@skip_identifier = options.delete(:skip_identifier)
|
17
|
+
|
18
|
+
if name
|
19
|
+
property = Karabiner::Property.new("name", name)
|
20
|
+
add_child(property)
|
21
|
+
end
|
22
|
+
|
23
|
+
options.each do |option, value|
|
24
|
+
raise "Unavailable option: #{option}" unless AVAILABLE_OPTIONS.include?(option)
|
25
|
+
|
26
|
+
property = Karabiner::Property.new(option, value)
|
27
|
+
add_child(property)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_xml
|
32
|
+
validate_name_existence
|
33
|
+
generate_identifier unless @skip_identifier
|
34
|
+
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def validate_name_existence
|
41
|
+
properties = search_childs(Karabiner::Property)
|
42
|
+
raise "Name property does not exist" unless properties.map(&:attr).include?("name")
|
43
|
+
end
|
44
|
+
|
45
|
+
def generate_identifier
|
46
|
+
properties = search_childs(Karabiner::Property)
|
47
|
+
return if properties.map(&:attr).include?("identifier")
|
48
|
+
|
49
|
+
name = properties.find { |p| p.attr == "name" }
|
50
|
+
generated_identifier = name.value.gsub(/[^a-zA-Z]/, "_").downcase
|
51
|
+
identifier = Karabiner::Property.new("identifier", "remap.#{generated_identifier}")
|
52
|
+
childs[1, 0] = identifier
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
class Karabiner::Key
|
2
|
+
KEYCODE_MAP = {
|
3
|
+
"0" => "KEY_0",
|
4
|
+
"1" => "KEY_1",
|
5
|
+
"2" => "KEY_2",
|
6
|
+
"3" => "KEY_3",
|
7
|
+
"4" => "KEY_4",
|
8
|
+
"5" => "KEY_5",
|
9
|
+
"6" => "KEY_6",
|
10
|
+
"7" => "KEY_7",
|
11
|
+
"8" => "KEY_8",
|
12
|
+
"9" => "KEY_9",
|
13
|
+
"Up" => "CURSOR_UP",
|
14
|
+
"Down" => "CURSOR_DOWN",
|
15
|
+
"Right" => "CURSOR_RIGHT",
|
16
|
+
"Left" => "CURSOR_LEFT",
|
17
|
+
"]" => "BRACKET_RIGHT",
|
18
|
+
"[" => "BRACKET_LEFT",
|
19
|
+
";" => "SEMICOLON",
|
20
|
+
"-" => "MINUS",
|
21
|
+
"," => "COMMA",
|
22
|
+
"." => "DOT",
|
23
|
+
"\\" => "BACKSLASH",
|
24
|
+
"/" => "SLASH",
|
25
|
+
"=" => "EQUAL",
|
26
|
+
"'" => "QUOTE",
|
27
|
+
"Ctrl_R" => "CONTROL_R",
|
28
|
+
"Ctrl_L" => "CONTROL_L",
|
29
|
+
"Opt_R" => "OPTION_R",
|
30
|
+
"Opt_L" => "OPTION_L",
|
31
|
+
"Cmd_R" => "COMMAND_R",
|
32
|
+
"Cmd_L" => "COMMAND_L",
|
33
|
+
}.freeze
|
34
|
+
PREFIX_MAP = {
|
35
|
+
"C" => "VK_CONTROL",
|
36
|
+
"Ctrl" => "VK_CONTROL",
|
37
|
+
"Cmd" => "VK_COMMAND",
|
38
|
+
"Shift" => "VK_SHIFT",
|
39
|
+
"M" => "VK_OPTION",
|
40
|
+
"Opt" => "VK_OPTION",
|
41
|
+
}.freeze
|
42
|
+
PREFIX_EXPRESSION = "(#{PREFIX_MAP.keys.map { |k| k + '-' }.join('|')})"
|
43
|
+
|
44
|
+
def initialize(expression)
|
45
|
+
@expression = expression
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
key_combination(@expression)
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def key_combination(raw_combination)
|
55
|
+
raw_prefixes, raw_key = split_key_combination(raw_combination)
|
56
|
+
return key_expression(raw_key) if raw_prefixes.empty?
|
57
|
+
|
58
|
+
prefixes = raw_prefixes.map { |raw_prefix| PREFIX_MAP[raw_prefix] }
|
59
|
+
"#{key_expression(raw_key)}, #{prefixes.join(' | ')}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def key_expression(raw_key)
|
63
|
+
case raw_key
|
64
|
+
when /^(#{KEYCODE_MAP.keys.map { |k| Regexp.escape(k) }.join('|')})$/
|
65
|
+
"KeyCode::#{KEYCODE_MAP[raw_key]}"
|
66
|
+
else
|
67
|
+
raw_key = raw_key.upcase unless raw_key.match(/^VK_/)
|
68
|
+
"KeyCode::#{raw_key}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def split_key_combination(raw_combination)
|
73
|
+
prefixes = []
|
74
|
+
key = raw_combination.dup
|
75
|
+
|
76
|
+
while key.match(/^#{PREFIX_EXPRESSION}/)
|
77
|
+
key.gsub!(/^#{PREFIX_EXPRESSION}/) do
|
78
|
+
prefixes << $1.gsub(/-$/, "")
|
79
|
+
""
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
[prefixes, key]
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Karabiner::Property
|
2
|
+
include Karabiner::XmlTree
|
3
|
+
|
4
|
+
def initialize(attr, value, options = {})
|
5
|
+
@attr = attr.to_s
|
6
|
+
@value = value
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
attr_accessor :attr, :value
|
10
|
+
|
11
|
+
def to_xml
|
12
|
+
open_tag = @options.map { |a, v| "#{a}=\"#{v}\"" }.unshift(attr).join(" ")
|
13
|
+
"<#{open_tag}>#{value}</#{attr}>"
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "karabiner/key"
|
2
|
+
require "karabiner/property"
|
3
|
+
|
4
|
+
class Karabiner::Remap < Karabiner::Property
|
5
|
+
def initialize(from, to)
|
6
|
+
tos = [to].flatten
|
7
|
+
|
8
|
+
super(
|
9
|
+
"autogen",
|
10
|
+
[
|
11
|
+
"__KeyToKey__ #{Karabiner::Key.new(from)}",
|
12
|
+
*tos.map { |to| Karabiner::Key.new(to) },
|
13
|
+
].join(", "),
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "karabiner/invoke_history"
|
2
|
+
require "karabiner/vkopenurldef"
|
3
|
+
require "karabiner/dsl/root"
|
4
|
+
|
5
|
+
class Karabiner::Root
|
6
|
+
include Karabiner::XmlTree
|
7
|
+
include Karabiner::DSL::Root
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@configs = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_xml
|
14
|
+
Karabiner::InvokeHistory.registered_applications.each do |application|
|
15
|
+
vkopenurldef = Karabiner::Vkopenurldef.new(application)
|
16
|
+
add_child(vkopenurldef)
|
17
|
+
end
|
18
|
+
|
19
|
+
[
|
20
|
+
"<?xml version=\"1.0\"?>",
|
21
|
+
super(1),
|
22
|
+
].join("\n")
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def add_config(config)
|
28
|
+
@configs << config
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require "karabiner/xml_tree"
|
2
|
+
|
3
|
+
class Karabiner::Vkopenurldef
|
4
|
+
include Karabiner::XmlTree
|
5
|
+
|
6
|
+
def initialize(application)
|
7
|
+
name = Karabiner::Property.new("name", "KeyCode::VK_OPEN_URL_APP_#{application.gsub(/ /, "_")}")
|
8
|
+
url = Karabiner::Property.new("url", "/Applications/#{application}.app", type: "file")
|
9
|
+
add_child(name, url)
|
10
|
+
end
|
11
|
+
end
|