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
@@ -0,0 +1,42 @@
|
|
1
|
+
module Karabiner::XmlTree
|
2
|
+
attr_reader :parent
|
3
|
+
|
4
|
+
def add_child(*objects)
|
5
|
+
objects.each do |object|
|
6
|
+
childs << object
|
7
|
+
end
|
8
|
+
|
9
|
+
childs.each do |child|
|
10
|
+
child.parent = self
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def search_childs(klass)
|
15
|
+
childs.select { |c| c.is_a?(klass) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_xml(distance_between_childs = 0)
|
19
|
+
tag_name = self.class.to_s.split("::").last.downcase
|
20
|
+
newline_count = distance_between_childs + 1
|
21
|
+
|
22
|
+
[
|
23
|
+
"<#{tag_name}>",
|
24
|
+
childs.map(&:to_xml).join("\n" * newline_count).gsub(/^/, " "),
|
25
|
+
"</#{tag_name}>",
|
26
|
+
].join("\n")
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
attr_writer :parent
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def childs
|
36
|
+
@childs ||= []
|
37
|
+
end
|
38
|
+
|
39
|
+
def parent
|
40
|
+
@parent
|
41
|
+
end
|
42
|
+
end
|
data/lib/karabiner.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require "karabiner/cli"
|
2
|
+
require "karabiner/version"
|
3
|
+
require "karabiner/root"
|
4
|
+
require "unindent"
|
5
|
+
require "fileutils"
|
6
|
+
|
7
|
+
class Karabiner
|
8
|
+
XML_FILE_NAME = "private.xml"
|
9
|
+
XML_DIR = File.expand_path("~/Library/Application Support/Karabiner")
|
10
|
+
|
11
|
+
def initialize(config_path)
|
12
|
+
@config_path = config_path
|
13
|
+
Karabiner::InvokeHistory.clear_histroy
|
14
|
+
end
|
15
|
+
attr_reader :config_path
|
16
|
+
|
17
|
+
def apply_configuration
|
18
|
+
replace_private_xml
|
19
|
+
CLI.reload_xml
|
20
|
+
|
21
|
+
puts "Successfully updated Karabiner configuration"
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def replace_private_xml
|
27
|
+
FileUtils.mkdir_p(XML_DIR)
|
28
|
+
|
29
|
+
xml_path = File.join(XML_DIR, XML_FILE_NAME)
|
30
|
+
File.write(xml_path, new_xml)
|
31
|
+
end
|
32
|
+
|
33
|
+
def new_xml
|
34
|
+
return @new_xml if defined?(@new_xml)
|
35
|
+
validate_config_existence
|
36
|
+
|
37
|
+
root = Root.new
|
38
|
+
config = File.read(config_path)
|
39
|
+
root.instance_eval(config)
|
40
|
+
@new_xml = root.to_xml.gsub(/ *$/, "").concat("\n")
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate_config_existence
|
44
|
+
return if File.exists?(config_path)
|
45
|
+
|
46
|
+
File.write(config_path, <<-EOS.unindent)
|
47
|
+
#!/usr/bin/env ruby
|
48
|
+
|
49
|
+
# # Example
|
50
|
+
# item "Command+E to Command+W", not: "TERMINAL" do
|
51
|
+
# identifier "option.not_terminal_opt_e"
|
52
|
+
# autogen "__KeyToKey__ KeyCode::E, VK_COMMAND, KeyCode::W, ModifierFlag::COMMAND_L"
|
53
|
+
# end
|
54
|
+
EOS
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Karabiner::Appdef do
|
4
|
+
describe "#to_xml" do
|
5
|
+
it "returns valid xml from appdef with equal" do
|
6
|
+
appdef = Karabiner::Appdef.new("CHROME", equal: "com.google.Chrome")
|
7
|
+
expect(appdef.to_xml).to eq(<<-EOS.unindent.strip)
|
8
|
+
<appdef>
|
9
|
+
<appname>CHROME</appname>
|
10
|
+
<equal>com.google.Chrome</equal>
|
11
|
+
</appdef>
|
12
|
+
EOS
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns valid xml from appdef with prefix" do
|
16
|
+
appdef = Karabiner::Appdef.new("CHROME", prefix: "com")
|
17
|
+
expect(appdef.to_xml).to eq(<<-EOS.unindent.strip)
|
18
|
+
<appdef>
|
19
|
+
<appname>CHROME</appname>
|
20
|
+
<prefix>com</prefix>
|
21
|
+
</appdef>
|
22
|
+
EOS
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns valid xml from appdef with suffix" do
|
26
|
+
appdef = Karabiner::Appdef.new("CHROME", suffix: "Chrome")
|
27
|
+
expect(appdef.to_xml).to eq(<<-EOS.unindent.strip)
|
28
|
+
<appdef>
|
29
|
+
<appname>CHROME</appname>
|
30
|
+
<suffix>Chrome</suffix>
|
31
|
+
</appdef>
|
32
|
+
EOS
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Karabiner::CLI do
|
4
|
+
describe ".current_config" do
|
5
|
+
subject { described_class.current_config }
|
6
|
+
|
7
|
+
let(:cli_path) { Karabiner::CLI::CLI_PATH }
|
8
|
+
|
9
|
+
before do
|
10
|
+
allow_any_instance_of(Kernel).to receive(:'`').with("#{cli_path} changed").and_return(<<-EOS.unindent)
|
11
|
+
remap.command_k_to_command_l=1
|
12
|
+
repeat.initial_wait=100
|
13
|
+
repeat.wait=20
|
14
|
+
option.terminal_command_option=1
|
15
|
+
notsave.automatically_enable_keyboard_device=1
|
16
|
+
EOS
|
17
|
+
end
|
18
|
+
|
19
|
+
it "returns config hash" do
|
20
|
+
expect(subject).to eq({
|
21
|
+
"option.terminal_command_option" => "1",
|
22
|
+
"remap.command_k_to_command_l" => "1",
|
23
|
+
"repeat.initial_wait" => "100",
|
24
|
+
"repeat.wait" => "20",
|
25
|
+
"notsave.automatically_enable_keyboard_device" => "1",
|
26
|
+
})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Karabiner::Key do
|
4
|
+
describe "#to_s" do
|
5
|
+
EXPECTED_RESULTS = {
|
6
|
+
"a" => "KeyCode::A",
|
7
|
+
"b" => "KeyCode::B",
|
8
|
+
"c" => "KeyCode::C",
|
9
|
+
"d" => "KeyCode::D",
|
10
|
+
"e" => "KeyCode::E",
|
11
|
+
"f" => "KeyCode::F",
|
12
|
+
"g" => "KeyCode::G",
|
13
|
+
"h" => "KeyCode::H",
|
14
|
+
"i" => "KeyCode::I",
|
15
|
+
"j" => "KeyCode::J",
|
16
|
+
"k" => "KeyCode::K",
|
17
|
+
"l" => "KeyCode::L",
|
18
|
+
"m" => "KeyCode::M",
|
19
|
+
"n" => "KeyCode::N",
|
20
|
+
"o" => "KeyCode::O",
|
21
|
+
"p" => "KeyCode::P",
|
22
|
+
"q" => "KeyCode::Q",
|
23
|
+
"r" => "KeyCode::R",
|
24
|
+
"s" => "KeyCode::S",
|
25
|
+
"t" => "KeyCode::T",
|
26
|
+
"u" => "KeyCode::U",
|
27
|
+
"v" => "KeyCode::V",
|
28
|
+
"w" => "KeyCode::W",
|
29
|
+
"x" => "KeyCode::X",
|
30
|
+
"y" => "KeyCode::Y",
|
31
|
+
"z" => "KeyCode::Z",
|
32
|
+
"A" => "KeyCode::A",
|
33
|
+
"B" => "KeyCode::B",
|
34
|
+
"C" => "KeyCode::C",
|
35
|
+
"D" => "KeyCode::D",
|
36
|
+
"E" => "KeyCode::E",
|
37
|
+
"F" => "KeyCode::F",
|
38
|
+
"G" => "KeyCode::G",
|
39
|
+
"H" => "KeyCode::H",
|
40
|
+
"I" => "KeyCode::I",
|
41
|
+
"J" => "KeyCode::J",
|
42
|
+
"K" => "KeyCode::K",
|
43
|
+
"L" => "KeyCode::L",
|
44
|
+
"M" => "KeyCode::M",
|
45
|
+
"N" => "KeyCode::N",
|
46
|
+
"O" => "KeyCode::O",
|
47
|
+
"P" => "KeyCode::P",
|
48
|
+
"Q" => "KeyCode::Q",
|
49
|
+
"R" => "KeyCode::R",
|
50
|
+
"S" => "KeyCode::S",
|
51
|
+
"T" => "KeyCode::T",
|
52
|
+
"U" => "KeyCode::U",
|
53
|
+
"V" => "KeyCode::V",
|
54
|
+
"W" => "KeyCode::W",
|
55
|
+
"X" => "KeyCode::X",
|
56
|
+
"Y" => "KeyCode::Y",
|
57
|
+
"Z" => "KeyCode::Z",
|
58
|
+
"0" => "KeyCode::KEY_0",
|
59
|
+
"1" => "KeyCode::KEY_1",
|
60
|
+
"2" => "KeyCode::KEY_2",
|
61
|
+
"3" => "KeyCode::KEY_3",
|
62
|
+
"4" => "KeyCode::KEY_4",
|
63
|
+
"5" => "KeyCode::KEY_5",
|
64
|
+
"6" => "KeyCode::KEY_6",
|
65
|
+
"7" => "KeyCode::KEY_7",
|
66
|
+
"8" => "KeyCode::KEY_8",
|
67
|
+
"9" => "KeyCode::KEY_9",
|
68
|
+
"Up" => "KeyCode::CURSOR_UP",
|
69
|
+
"Down" => "KeyCode::CURSOR_DOWN",
|
70
|
+
"Right" => "KeyCode::CURSOR_RIGHT",
|
71
|
+
"Left" => "KeyCode::CURSOR_LEFT",
|
72
|
+
"]" => "KeyCode::BRACKET_RIGHT",
|
73
|
+
"[" => "KeyCode::BRACKET_LEFT",
|
74
|
+
";" => "KeyCode::SEMICOLON",
|
75
|
+
"-" => "KeyCode::MINUS",
|
76
|
+
"," => "KeyCode::COMMA",
|
77
|
+
"." => "KeyCode::DOT",
|
78
|
+
"\\" => "KeyCode::BACKSLASH",
|
79
|
+
"/" => "KeyCode::SLASH",
|
80
|
+
"=" => "KeyCode::EQUAL",
|
81
|
+
"'" => "KeyCode::QUOTE",
|
82
|
+
"Ctrl_R" => "KeyCode::CONTROL_R",
|
83
|
+
"Ctrl_L" => "KeyCode::CONTROL_L",
|
84
|
+
"Opt_R" => "KeyCode::OPTION_R",
|
85
|
+
"Opt_L" => "KeyCode::OPTION_L",
|
86
|
+
"Cmd_R" => "KeyCode::COMMAND_R",
|
87
|
+
"Cmd_L" => "KeyCode::COMMAND_L",
|
88
|
+
"Shift_R" => "KeyCode::SHIFT_R",
|
89
|
+
"Shift_L" => "KeyCode::SHIFT_L",
|
90
|
+
}.freeze
|
91
|
+
|
92
|
+
it "converts single key expression as expected" do
|
93
|
+
EXPECTED_RESULTS.each do |expression, result|
|
94
|
+
expect(described_class.new(expression).to_s).to eq(result)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it "converts double key combination as expected" do
|
99
|
+
Karabiner::Key::PREFIX_MAP.each do |prefix, vk|
|
100
|
+
key, keycode = EXPECTED_RESULTS.to_a.sample
|
101
|
+
expect(described_class.new("#{prefix}-#{key}").to_s).to eq("#{keycode}, #{vk}")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
it "converts triple key combination as expected" do
|
106
|
+
key, keycode = EXPECTED_RESULTS.to_a.sample
|
107
|
+
unique_maps = Karabiner::Key::PREFIX_MAP.to_a.sort_by { rand }.uniq { |a| a[1] }
|
108
|
+
unique_maps.combination(2) do |(prefix1, vk1), (prefix2, vk2)|
|
109
|
+
expect(described_class.new("#{prefix1}-#{prefix2}-#{key}").to_s).to eq("#{keycode}, #{vk1} | #{vk2}")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Karabiner::Remap do
|
4
|
+
describe "#to_xml" do
|
5
|
+
it "converts key remap to autogen tag" do
|
6
|
+
expect(Karabiner::Remap.new("Cmd-Shift-]", "Opt-Ctrl-Up").to_xml).
|
7
|
+
to eq("<autogen>__KeyToKey__ KeyCode::BRACKET_RIGHT, VK_COMMAND | VK_SHIFT, KeyCode::CURSOR_UP, VK_OPTION | VK_CONTROL</autogen>")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,335 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "tempfile"
|
3
|
+
|
4
|
+
describe Karabiner do
|
5
|
+
let!(:config) { Tempfile.new(".karabiner") }
|
6
|
+
let(:xml_dir) { "/tmp" }
|
7
|
+
let(:xml_path) { File.join(xml_dir, Karabiner::XML_FILE_NAME) }
|
8
|
+
let(:result) { File.read(xml_path) }
|
9
|
+
|
10
|
+
before do
|
11
|
+
stub_const("Karabiner::XML_DIR", xml_dir)
|
12
|
+
allow(Karabiner::CLI).to receive(:reload_xml)
|
13
|
+
|
14
|
+
# Silence stdout
|
15
|
+
allow_any_instance_of(Kernel).to receive(:puts)
|
16
|
+
end
|
17
|
+
|
18
|
+
after do
|
19
|
+
config.close!
|
20
|
+
end
|
21
|
+
|
22
|
+
def prepare_karabiner(karabiner)
|
23
|
+
config.write(karabiner)
|
24
|
+
config.rewind
|
25
|
+
end
|
26
|
+
|
27
|
+
def expect_result(expected_result)
|
28
|
+
karabiner = Karabiner.new(config.path)
|
29
|
+
karabiner.apply_configuration
|
30
|
+
expect(result).to eq(expected_result)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "accepts blank config" do
|
34
|
+
prepare_karabiner("")
|
35
|
+
|
36
|
+
expect_result(<<-EOS.unindent)
|
37
|
+
<?xml version="1.0"?>
|
38
|
+
<root>
|
39
|
+
|
40
|
+
</root>
|
41
|
+
EOS
|
42
|
+
end
|
43
|
+
|
44
|
+
it "accepts cmd combination" do
|
45
|
+
prepare_karabiner(<<-EOS)
|
46
|
+
item "Command+A to Command+B" do
|
47
|
+
remap "Cmd-A", to: "Cmd-B"
|
48
|
+
end
|
49
|
+
EOS
|
50
|
+
|
51
|
+
expect_result(<<-EOS.unindent)
|
52
|
+
<?xml version="1.0"?>
|
53
|
+
<root>
|
54
|
+
<item>
|
55
|
+
<name>Command+A to Command+B</name>
|
56
|
+
<identifier>remap.command_a_to_command_b</identifier>
|
57
|
+
<autogen>__KeyToKey__ KeyCode::A, VK_COMMAND, KeyCode::B, VK_COMMAND</autogen>
|
58
|
+
</item>
|
59
|
+
</root>
|
60
|
+
EOS
|
61
|
+
end
|
62
|
+
|
63
|
+
it "accepts multiple remaps" do
|
64
|
+
prepare_karabiner(<<-EOS)
|
65
|
+
item "multiple remaps" do
|
66
|
+
remap "Cmd-A", to: "Cmd-B"
|
67
|
+
remap "Shift-A", to: "Shift-B"
|
68
|
+
end
|
69
|
+
EOS
|
70
|
+
|
71
|
+
expect_result(<<-EOS.unindent)
|
72
|
+
<?xml version="1.0"?>
|
73
|
+
<root>
|
74
|
+
<item>
|
75
|
+
<name>multiple remaps</name>
|
76
|
+
<identifier>remap.multiple_remaps</identifier>
|
77
|
+
<autogen>__KeyToKey__ KeyCode::A, VK_COMMAND, KeyCode::B, VK_COMMAND</autogen>
|
78
|
+
<autogen>__KeyToKey__ KeyCode::A, VK_SHIFT, KeyCode::B, VK_SHIFT</autogen>
|
79
|
+
</item>
|
80
|
+
</root>
|
81
|
+
EOS
|
82
|
+
end
|
83
|
+
|
84
|
+
it "accepts multiple items" do
|
85
|
+
prepare_karabiner(<<-EOS)
|
86
|
+
item "first item" do
|
87
|
+
remap "Cmd-C-A", to: "Cmd-M-B"
|
88
|
+
end
|
89
|
+
|
90
|
+
item "second item" do
|
91
|
+
remap "Shift-Opt-A", to: "Shift-Cmd-B"
|
92
|
+
end
|
93
|
+
EOS
|
94
|
+
|
95
|
+
expect_result(<<-EOS.unindent)
|
96
|
+
<?xml version="1.0"?>
|
97
|
+
<root>
|
98
|
+
<item>
|
99
|
+
<name>first item</name>
|
100
|
+
<identifier>remap.first_item</identifier>
|
101
|
+
<autogen>__KeyToKey__ KeyCode::A, VK_COMMAND | VK_CONTROL, KeyCode::B, VK_COMMAND | VK_OPTION</autogen>
|
102
|
+
</item>
|
103
|
+
|
104
|
+
<item>
|
105
|
+
<name>second item</name>
|
106
|
+
<identifier>remap.second_item</identifier>
|
107
|
+
<autogen>__KeyToKey__ KeyCode::A, VK_SHIFT | VK_OPTION, KeyCode::B, VK_SHIFT | VK_COMMAND</autogen>
|
108
|
+
</item>
|
109
|
+
</root>
|
110
|
+
EOS
|
111
|
+
end
|
112
|
+
|
113
|
+
it "accepts appdef and app option" do
|
114
|
+
prepare_karabiner(<<-EOS)
|
115
|
+
appdef "CHROME", equal: "com.google.Chrome"
|
116
|
+
|
117
|
+
item "Command+K to Command+L", only: "CHROME" do
|
118
|
+
remap "Cmd-K", to: "Cmd-L"
|
119
|
+
end
|
120
|
+
EOS
|
121
|
+
|
122
|
+
expect_result(<<-EOS.unindent)
|
123
|
+
<?xml version="1.0"?>
|
124
|
+
<root>
|
125
|
+
<appdef>
|
126
|
+
<appname>CHROME</appname>
|
127
|
+
<equal>com.google.Chrome</equal>
|
128
|
+
</appdef>
|
129
|
+
|
130
|
+
<item>
|
131
|
+
<name>Command+K to Command+L</name>
|
132
|
+
<identifier>remap.command_k_to_command_l</identifier>
|
133
|
+
<only>CHROME</only>
|
134
|
+
<autogen>__KeyToKey__ KeyCode::K, VK_COMMAND, KeyCode::L, VK_COMMAND</autogen>
|
135
|
+
</item>
|
136
|
+
</root>
|
137
|
+
EOS
|
138
|
+
end
|
139
|
+
|
140
|
+
it "accepts config and show_message" do
|
141
|
+
prepare_karabiner(<<-EOS)
|
142
|
+
item "CapsLock ON", config_not: "notsave.private_capslock_on" do
|
143
|
+
remap "Cmd-L", to: ["capslock", "VK_CONFIG_FORCE_ON_notsave_private_capslock_on"]
|
144
|
+
end
|
145
|
+
|
146
|
+
item "CapsLock OFF", config_only: "notsave.private_capslock_on" do
|
147
|
+
remap "Cmd-L", to: ["capslock", "VK_CONFIG_FORCE_OFF_notsave_private_capslock_on"]
|
148
|
+
end
|
149
|
+
|
150
|
+
item "CapsLock Mode" do
|
151
|
+
identifier "notsave.private_capslock_on", vk_config: "true"
|
152
|
+
show_message "CapsLock"
|
153
|
+
end
|
154
|
+
EOS
|
155
|
+
|
156
|
+
expect_result(<<-EOS.unindent)
|
157
|
+
<?xml version="1.0"?>
|
158
|
+
<root>
|
159
|
+
<item>
|
160
|
+
<name>CapsLock ON</name>
|
161
|
+
<identifier>remap.capslock_on</identifier>
|
162
|
+
<config_not>notsave.private_capslock_on</config_not>
|
163
|
+
<autogen>__KeyToKey__ KeyCode::L, VK_COMMAND, KeyCode::CAPSLOCK, KeyCode::VK_CONFIG_FORCE_ON_notsave_private_capslock_on</autogen>
|
164
|
+
</item>
|
165
|
+
|
166
|
+
<item>
|
167
|
+
<name>CapsLock OFF</name>
|
168
|
+
<identifier>remap.capslock_off</identifier>
|
169
|
+
<config_only>notsave.private_capslock_on</config_only>
|
170
|
+
<autogen>__KeyToKey__ KeyCode::L, VK_COMMAND, KeyCode::CAPSLOCK, KeyCode::VK_CONFIG_FORCE_OFF_notsave_private_capslock_on</autogen>
|
171
|
+
</item>
|
172
|
+
|
173
|
+
<item>
|
174
|
+
<name>CapsLock Mode</name>
|
175
|
+
<identifier vk_config="true">notsave.private_capslock_on</identifier>
|
176
|
+
<autogen>__ShowStatusMessage__ CapsLock</autogen>
|
177
|
+
</item>
|
178
|
+
</root>
|
179
|
+
EOS
|
180
|
+
end
|
181
|
+
|
182
|
+
it "accepts implicit autogen selection" do
|
183
|
+
prepare_karabiner(<<-EOS)
|
184
|
+
item "Control+LeftClick to Command+LeftClick" do
|
185
|
+
autogen "__PointingButtonToPointingButton__ PointingButton::LEFT, MODIFIERFLAG_EITHER_LEFT_OR_RIGHT_CONTROL, PointingButton::LEFT, MODIFIERFLAG_EITHER_LEFT_OR_RIGHT_COMMAND"
|
186
|
+
end
|
187
|
+
EOS
|
188
|
+
|
189
|
+
expect_result(<<-EOS.unindent)
|
190
|
+
<?xml version="1.0"?>
|
191
|
+
<root>
|
192
|
+
<item>
|
193
|
+
<name>Control+LeftClick to Command+LeftClick</name>
|
194
|
+
<identifier>remap.control_leftclick_to_command_leftclick</identifier>
|
195
|
+
<autogen>__PointingButtonToPointingButton__ PointingButton::LEFT, MODIFIERFLAG_EITHER_LEFT_OR_RIGHT_CONTROL, PointingButton::LEFT, MODIFIERFLAG_EITHER_LEFT_OR_RIGHT_COMMAND</autogen>
|
196
|
+
</item>
|
197
|
+
</root>
|
198
|
+
EOS
|
199
|
+
end
|
200
|
+
|
201
|
+
it "application invoking" do
|
202
|
+
prepare_karabiner(<<-EOS)
|
203
|
+
item "Application shortcuts" do
|
204
|
+
remap "C-o", to: invoke("YoruFukurou")
|
205
|
+
remap "C-u", to: invoke("Google Chrome")
|
206
|
+
remap "C-h", to: invoke("iTerm")
|
207
|
+
end
|
208
|
+
|
209
|
+
item "duplicate app" do
|
210
|
+
remap "C-a", to: invoke("YoruFukurou")
|
211
|
+
end
|
212
|
+
EOS
|
213
|
+
|
214
|
+
expect_result(<<-EOS.unindent)
|
215
|
+
<?xml version="1.0"?>
|
216
|
+
<root>
|
217
|
+
<item>
|
218
|
+
<name>Application shortcuts</name>
|
219
|
+
<identifier>remap.application_shortcuts</identifier>
|
220
|
+
<autogen>__KeyToKey__ KeyCode::O, VK_CONTROL, KeyCode::VK_OPEN_URL_APP_YoruFukurou</autogen>
|
221
|
+
<autogen>__KeyToKey__ KeyCode::U, VK_CONTROL, KeyCode::VK_OPEN_URL_APP_Google_Chrome</autogen>
|
222
|
+
<autogen>__KeyToKey__ KeyCode::H, VK_CONTROL, KeyCode::VK_OPEN_URL_APP_iTerm</autogen>
|
223
|
+
</item>
|
224
|
+
|
225
|
+
<item>
|
226
|
+
<name>duplicate app</name>
|
227
|
+
<identifier>remap.duplicate_app</identifier>
|
228
|
+
<autogen>__KeyToKey__ KeyCode::A, VK_CONTROL, KeyCode::VK_OPEN_URL_APP_YoruFukurou</autogen>
|
229
|
+
</item>
|
230
|
+
|
231
|
+
<vkopenurldef>
|
232
|
+
<name>KeyCode::VK_OPEN_URL_APP_YoruFukurou</name>
|
233
|
+
<url type="file">/Applications/YoruFukurou.app</url>
|
234
|
+
</vkopenurldef>
|
235
|
+
|
236
|
+
<vkopenurldef>
|
237
|
+
<name>KeyCode::VK_OPEN_URL_APP_Google_Chrome</name>
|
238
|
+
<url type="file">/Applications/Google Chrome.app</url>
|
239
|
+
</vkopenurldef>
|
240
|
+
|
241
|
+
<vkopenurldef>
|
242
|
+
<name>KeyCode::VK_OPEN_URL_APP_iTerm</name>
|
243
|
+
<url type="file">/Applications/iTerm.app</url>
|
244
|
+
</vkopenurldef>
|
245
|
+
</root>
|
246
|
+
EOS
|
247
|
+
end
|
248
|
+
|
249
|
+
it "accepts group items" do
|
250
|
+
prepare_karabiner(<<-EOS)
|
251
|
+
group "Option" do
|
252
|
+
item "First" do
|
253
|
+
identifier "option.option_first"
|
254
|
+
end
|
255
|
+
|
256
|
+
item "Second" do
|
257
|
+
identifier "option.option_second"
|
258
|
+
end
|
259
|
+
end
|
260
|
+
EOS
|
261
|
+
|
262
|
+
expect_result(<<-EOS.unindent)
|
263
|
+
<?xml version="1.0"?>
|
264
|
+
<root>
|
265
|
+
<item>
|
266
|
+
<name>Option</name>
|
267
|
+
<item>
|
268
|
+
<name>First</name>
|
269
|
+
<identifier>option.option_first</identifier>
|
270
|
+
</item>
|
271
|
+
<item>
|
272
|
+
<name>Second</name>
|
273
|
+
<identifier>option.option_second</identifier>
|
274
|
+
</item>
|
275
|
+
</item>
|
276
|
+
</root>
|
277
|
+
EOS
|
278
|
+
end
|
279
|
+
|
280
|
+
context "when items are surrounded by config" do
|
281
|
+
it "accepts cmd combination" do
|
282
|
+
prepare_karabiner(<<-EOS)
|
283
|
+
config "Default" do
|
284
|
+
item "Command+A to Command+B" do
|
285
|
+
remap "Cmd-A", to: "Cmd-B"
|
286
|
+
end
|
287
|
+
end
|
288
|
+
EOS
|
289
|
+
|
290
|
+
expect_result(<<-EOS.unindent)
|
291
|
+
<?xml version="1.0"?>
|
292
|
+
<root>
|
293
|
+
<item>
|
294
|
+
<name>Command+A to Command+B</name>
|
295
|
+
<identifier>remap.command_a_to_command_b</identifier>
|
296
|
+
<autogen>__KeyToKey__ KeyCode::A, VK_COMMAND, KeyCode::B, VK_COMMAND</autogen>
|
297
|
+
</item>
|
298
|
+
</root>
|
299
|
+
EOS
|
300
|
+
end
|
301
|
+
|
302
|
+
it "accepts group items" do
|
303
|
+
prepare_karabiner(<<-EOS)
|
304
|
+
config "Original" do
|
305
|
+
group "Option" do
|
306
|
+
item "First" do
|
307
|
+
identifier "option.option_first"
|
308
|
+
end
|
309
|
+
|
310
|
+
item "Second" do
|
311
|
+
identifier "option.option_second"
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
EOS
|
316
|
+
|
317
|
+
expect_result(<<-EOS.unindent)
|
318
|
+
<?xml version="1.0"?>
|
319
|
+
<root>
|
320
|
+
<item>
|
321
|
+
<name>Option</name>
|
322
|
+
<item>
|
323
|
+
<name>First</name>
|
324
|
+
<identifier>option.option_first</identifier>
|
325
|
+
</item>
|
326
|
+
<item>
|
327
|
+
<name>Second</name>
|
328
|
+
<identifier>option.option_second</identifier>
|
329
|
+
</item>
|
330
|
+
</item>
|
331
|
+
</root>
|
332
|
+
EOS
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
data/spec/spec_helper.rb
ADDED