keyremac 0.0.1
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 +17 -0
- data/.travis.yml +3 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +8 -0
- data/keyremac.gemspec +26 -0
- data/lib/keyremac/base.rb +142 -0
- data/lib/keyremac/dump.rb +97 -0
- data/lib/keyremac/key.rb +132 -0
- data/lib/keyremac/version.rb +3 -0
- data/lib/keyremac.rb +46 -0
- data/samples/sample.rb +67 -0
- data/spec/dump_spec.rb +160 -0
- data/spec/keyremac_spec.rb +139 -0
- metadata +117 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 56a85964a7ed2a53cffef78bb058925b6af0cd59
|
4
|
+
data.tar.gz: cb87ed2b0ef6002a218c859f04f502c671260bb9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e8ff12e76d5080364666e61023c6269e0f91198aafce3f602fe50766201f2e48a1989440e45d1b622f5c0aa1587f7dad17f7a0c77970555dc775757a6da2f560
|
7
|
+
data.tar.gz: f952a9b53d7d7a49e79e213e694b8ba5c20bfdba34e04cadc3fa662d7a5bab44daa6c11ea552fe4f2aa595b9557a7a61117d34433e184edb4c586e4877606cab
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 keqh
|
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,29 @@
|
|
1
|
+
# Keyremac
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'keyremac'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install keyremac
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/keyremac.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 'keyremac/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "keyremac"
|
8
|
+
spec.version = Keyremac::VERSION
|
9
|
+
spec.authors = ["keqh"]
|
10
|
+
spec.email = ["keqh.keqh@gmail.com"]
|
11
|
+
spec.description = %q{KeyRemap4MacBook private.xml generator}
|
12
|
+
spec.summary = %q{KeyRemap4MacBook private.xml generator}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
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", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "awesome_print"
|
24
|
+
|
25
|
+
spec.add_dependency "builder"
|
26
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'awesome_print'
|
2
|
+
require 'builder'
|
3
|
+
|
4
|
+
require 'keyremac/key'
|
5
|
+
|
6
|
+
module Keyremac
|
7
|
+
# focus
|
8
|
+
# ====================================
|
9
|
+
|
10
|
+
@@focus = []
|
11
|
+
|
12
|
+
def self.focus
|
13
|
+
@@focus
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.get_focus
|
17
|
+
@@focus.last
|
18
|
+
end
|
19
|
+
def self.set_focus(container, &block)
|
20
|
+
@@focus.push container
|
21
|
+
yield
|
22
|
+
@@focus.pop
|
23
|
+
end
|
24
|
+
|
25
|
+
# autogen
|
26
|
+
# ====================================
|
27
|
+
|
28
|
+
class KeyToKey < Struct.new(:from, :to); end
|
29
|
+
class KeyToConsumer < Struct.new(:from, :to); end
|
30
|
+
class KeyOverlaidModifier # < Struct.new(:key, :mod, :keys)
|
31
|
+
attr_reader :key, :mod, :keys, :repeat
|
32
|
+
def initialize(key, mod, keys: [], repeat: false)
|
33
|
+
@key = key
|
34
|
+
@mod = mod
|
35
|
+
@keys = keys == [] ? [key] : keys
|
36
|
+
@repeat = repeat
|
37
|
+
end
|
38
|
+
|
39
|
+
def repeat?
|
40
|
+
@repeat
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# container
|
45
|
+
# ====================================
|
46
|
+
|
47
|
+
module Container
|
48
|
+
attr_accessor :children
|
49
|
+
|
50
|
+
def add(rule)
|
51
|
+
children << rule
|
52
|
+
end
|
53
|
+
|
54
|
+
def method_missing(method_name, *args, &block)
|
55
|
+
method_name = method_name.to_s
|
56
|
+
if method_name[-1] == '_'
|
57
|
+
raw = Raw.new method_name.chomp('_')
|
58
|
+
if block
|
59
|
+
Keyremac.set_focus raw do
|
60
|
+
raw.instance_eval(&block)
|
61
|
+
end
|
62
|
+
else
|
63
|
+
raw.children = args[0]
|
64
|
+
end
|
65
|
+
@children << raw
|
66
|
+
raw
|
67
|
+
else
|
68
|
+
raise NoMethodError, method_name
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class Raw
|
74
|
+
include Container
|
75
|
+
def initialize(tag, children = [])
|
76
|
+
@tag = tag
|
77
|
+
@children = children
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class Item
|
82
|
+
include Container
|
83
|
+
|
84
|
+
@@identifier = 'a'
|
85
|
+
def self.identifier
|
86
|
+
@@identifier
|
87
|
+
end
|
88
|
+
def self.reset_identifier
|
89
|
+
@@identifier = 'a'
|
90
|
+
end
|
91
|
+
|
92
|
+
def initialize(name = nil)
|
93
|
+
@children = []
|
94
|
+
@name = name || @@identifier
|
95
|
+
@@identifier = @@identifier.succ
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class Root
|
100
|
+
include Container
|
101
|
+
|
102
|
+
attr_reader :root_item
|
103
|
+
|
104
|
+
def initialize
|
105
|
+
@root_item = Item.new 'root_item'
|
106
|
+
Keyremac.focus.clear
|
107
|
+
Keyremac.focus << @root_item
|
108
|
+
@children = []
|
109
|
+
end
|
110
|
+
|
111
|
+
def item(app: nil, inputsource: nil, &block)
|
112
|
+
Item.new.tap { |item|
|
113
|
+
item.only_ app if app
|
114
|
+
item.inputsource_only_ inputsource if inputsource
|
115
|
+
@children << item
|
116
|
+
Keyremac.set_focus item do
|
117
|
+
item.instance_eval(&block)
|
118
|
+
end
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
def app(only, **options, &block)
|
123
|
+
options[:app] = only
|
124
|
+
item(**options, &block)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# delegator
|
129
|
+
# ====================================
|
130
|
+
|
131
|
+
module Delegator
|
132
|
+
@@root = Root.new
|
133
|
+
|
134
|
+
def get_root
|
135
|
+
@@root
|
136
|
+
end
|
137
|
+
|
138
|
+
def method_missing(method_name, *args, &block)
|
139
|
+
@@root.send(method_name, *args, &block)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Keyremac
|
2
|
+
|
3
|
+
# key
|
4
|
+
# ===========================
|
5
|
+
|
6
|
+
class Key
|
7
|
+
def dump(xml)
|
8
|
+
if @mods.empty?
|
9
|
+
"KeyCode::#{code.upcase}"
|
10
|
+
else
|
11
|
+
mods = @mods.to_a
|
12
|
+
mods = mods.map { |mod|
|
13
|
+
mod = mod.to_s
|
14
|
+
if mod =~ /^VK_/
|
15
|
+
mod
|
16
|
+
else
|
17
|
+
"ModifierFlag::#{mod}"
|
18
|
+
end
|
19
|
+
}
|
20
|
+
mods = mods.join(' | ')
|
21
|
+
"KeyCode::#{code.upcase}, #{mods}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class ConsumerKey
|
27
|
+
def dump(xml)
|
28
|
+
"ConsumerKeyCode::#{code.upcase}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# autogen
|
33
|
+
# ===========================
|
34
|
+
|
35
|
+
class KeyToKey
|
36
|
+
def dump(xml)
|
37
|
+
seqs = [from, *to].map{ |k| k.dump(xml) }.join(', ')
|
38
|
+
xml.autogen "__KeyToKey__ #{seqs}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class KeyToConsumer
|
43
|
+
def dump(xml)
|
44
|
+
xml.autogen "__KeyToConsumer__ #{from.dump(xml)}, #{to.dump(xml)}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class KeyOverlaidModifier
|
49
|
+
def dump(xml)
|
50
|
+
seqs = [key, mod, *keys].map { |k| k.dump(xml) }.join(', ')
|
51
|
+
autogen = repeat ? '__KeyOverlaidModifierWithRepeat__' : '__KeyOverlaidModifier__'
|
52
|
+
xml.autogen "#{autogen} #{seqs}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# container
|
57
|
+
# ===========================
|
58
|
+
|
59
|
+
class Raw
|
60
|
+
def dump(xml)
|
61
|
+
if @children.class == String
|
62
|
+
xml.tag! @tag, @children
|
63
|
+
else
|
64
|
+
xml.tag! @tag do
|
65
|
+
@children.each { |child|
|
66
|
+
child.dump xml
|
67
|
+
}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class Item
|
74
|
+
def dump(xml)
|
75
|
+
xml.item do
|
76
|
+
xml.name @name
|
77
|
+
xml.identifier "private.#{@name}"
|
78
|
+
@children.each { |child|
|
79
|
+
child.dump xml
|
80
|
+
}
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class Root
|
86
|
+
def dump(xml = nil)
|
87
|
+
xml ||= Builder::XmlMarkup.new(indent: 2)
|
88
|
+
xml.instruct!
|
89
|
+
xml.root do
|
90
|
+
@root_item.dump xml
|
91
|
+
@children.each { |child|
|
92
|
+
child.dump(xml)
|
93
|
+
}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/keyremac/key.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
|
2
|
+
require 'keyremac/base'
|
3
|
+
|
4
|
+
require 'set'
|
5
|
+
|
6
|
+
module Keyremac
|
7
|
+
|
8
|
+
CONSUMER_KEYS = [
|
9
|
+
'BRIGHTNESS_DOWN',
|
10
|
+
'BRIGHTNESS_UP',
|
11
|
+
'KEYBOARDLIGHT_OFF',
|
12
|
+
'KEYBOARDLIGHT_LOW',
|
13
|
+
'KEYBOARDLIGHT_HIGH',
|
14
|
+
'MUSIC_PREV',
|
15
|
+
'MUSIC_PLAY',
|
16
|
+
'MUSIC_NEXT',
|
17
|
+
'MUSIC_PREV_18',
|
18
|
+
'MUSIC_NEXT_17',
|
19
|
+
'VOLUME_MUTE',
|
20
|
+
'VOLUME_DOWN',
|
21
|
+
'VOLUME_UP',
|
22
|
+
'EJECT',
|
23
|
+
'POWER',
|
24
|
+
'NUMLOCK',
|
25
|
+
'VIDEO_MIRROR',
|
26
|
+
]
|
27
|
+
|
28
|
+
SYMBOL_TABLE = {
|
29
|
+
'`' => 'BACKQUOTE',
|
30
|
+
'\\' => 'BACKSLASH',
|
31
|
+
'[' => 'BRACKET_LEFT',
|
32
|
+
']' => 'BRACKET_RIGHT',
|
33
|
+
',' => 'COMMA',
|
34
|
+
'.' => 'DOT',
|
35
|
+
'=' => 'EQUAL',
|
36
|
+
'-' => 'MINUS',
|
37
|
+
'\'' => 'QUOTE',
|
38
|
+
';' => 'SEMICOLON',
|
39
|
+
'0' => 'KEY_0',
|
40
|
+
'1' => 'KEY_1',
|
41
|
+
'2' => 'KEY_2',
|
42
|
+
'3' => 'KEY_3',
|
43
|
+
'4' => 'KEY_4',
|
44
|
+
'5' => 'KEY_5',
|
45
|
+
'6' => 'KEY_6',
|
46
|
+
'7' => 'KEY_7',
|
47
|
+
'8' => 'KEY_8',
|
48
|
+
'9' => 'KEY_9',
|
49
|
+
}
|
50
|
+
|
51
|
+
SHIFT_TABLE = Hash[
|
52
|
+
%q[!@#$%^&*()_+~QWERTYUIOP{}ASDFGHJKL:"|ZXCVBNM<>?~].each_char.to_a.zip(
|
53
|
+
%q(1234567890-=`qwertyuiop[]asdfghjkl;'\zxcvbnm,./`).each_char.to_a
|
54
|
+
)]
|
55
|
+
|
56
|
+
module Keyable
|
57
|
+
{
|
58
|
+
ctrl: :VK_CONTROL,
|
59
|
+
shift: :VK_SHIFT,
|
60
|
+
opt: :VK_OPTION,
|
61
|
+
cmd: :VK_COMMAND,
|
62
|
+
extra1: :EXTRA1,
|
63
|
+
none: :NONE,
|
64
|
+
}.each { |k,v|
|
65
|
+
define_method(k, -> { self.to_key.add_mod v })
|
66
|
+
define_method("#{k}?", -> { self.to_key.mods.include? v })
|
67
|
+
}
|
68
|
+
|
69
|
+
def to(*keys)
|
70
|
+
key = keys.first.to_key
|
71
|
+
autogen = if key.consumer_key?
|
72
|
+
Keyremac::KeyToConsumer.new self.to_key, key
|
73
|
+
else
|
74
|
+
Keyremac::KeyToKey.new self.to_key, keys.map(&:to_key)
|
75
|
+
end
|
76
|
+
Keyremac.get_focus.add autogen
|
77
|
+
autogen
|
78
|
+
end
|
79
|
+
|
80
|
+
def overlaid(mod, keys: [], repeat: false)
|
81
|
+
autogen = Keyremac::KeyOverlaidModifier.new self.to_key, mod.to_key, keys: keys.map(&:to_key), repeat: repeat
|
82
|
+
Keyremac.get_focus.add autogen
|
83
|
+
autogen
|
84
|
+
end
|
85
|
+
|
86
|
+
def consumer_key?
|
87
|
+
false
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_key
|
91
|
+
if Keyremac::CONSUMER_KEYS.include?(self.to_s)
|
92
|
+
Keyremac::ConsumerKey.new self.to_s
|
93
|
+
else
|
94
|
+
Keyremac::Key.new self.to_s
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class ConsumerKey < Struct.new(:code)
|
100
|
+
include Keyable
|
101
|
+
def consumer_key?; true end
|
102
|
+
def to_key; self end
|
103
|
+
end
|
104
|
+
|
105
|
+
class Key
|
106
|
+
include Keyable
|
107
|
+
attr_reader :code, :mods
|
108
|
+
|
109
|
+
def to_key
|
110
|
+
self
|
111
|
+
end
|
112
|
+
|
113
|
+
def initialize(name)
|
114
|
+
@mods = Set.new
|
115
|
+
|
116
|
+
if key = SHIFT_TABLE[name]
|
117
|
+
@code = SYMBOL_TABLE[key] || key
|
118
|
+
self.shift
|
119
|
+
else
|
120
|
+
@code = SYMBOL_TABLE[name] || name
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_mod(mod)
|
125
|
+
@mods.add mod
|
126
|
+
self
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
class Symbol; include Keyremac::Keyable; end
|
132
|
+
class String; include Keyremac::Keyable; end
|
data/lib/keyremac.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require "keyremac/version"
|
2
|
+
require 'keyremac/base'
|
3
|
+
require 'keyremac/dump'
|
4
|
+
|
5
|
+
require 'rexml/document'
|
6
|
+
|
7
|
+
module Keyremac
|
8
|
+
def self.dump
|
9
|
+
puts get_root.dump
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.collect_identifiers
|
13
|
+
xml = get_root.dump
|
14
|
+
doc = REXML::Document.new(xml)
|
15
|
+
|
16
|
+
result = []
|
17
|
+
doc.elements.each('//identifier') {|e|
|
18
|
+
result << e.text
|
19
|
+
}
|
20
|
+
result
|
21
|
+
end
|
22
|
+
|
23
|
+
CLI_PATH = '/Applications/KeyRemap4MacBook.app/Contents/Applications/KeyRemap4MacBook_cli.app/Contents/MacOS/KeyRemap4MacBook_cli'
|
24
|
+
DEFAULT_SETTINGS_PATH = '~/Library/Application Support/KeyRemap4MacBook/private.xml'
|
25
|
+
|
26
|
+
def self.reload
|
27
|
+
File.write File.expand_path(DEFAULT_SETTINGS_PATH), get_root.dump
|
28
|
+
`#{CLI_PATH} reloadxml`
|
29
|
+
self.collect_identifiers.each { |id|
|
30
|
+
`#{CLI_PATH} enable #{id}`
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.run
|
35
|
+
require 'optparse'
|
36
|
+
OptionParser.new { |op|
|
37
|
+
op.on('--dump', 'dump private.xml') { Keyremac::dump }
|
38
|
+
op.on('--reload', 'reload private.xml') { Keyremac::reload }
|
39
|
+
op.on('--ids', 'collect identifiers') { puts Keyremac::collect_identifiers }
|
40
|
+
}.parse!(ARGV.dup)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
include Keyremac::Delegator
|
45
|
+
|
46
|
+
at_exit { Keyremac::run }
|
data/samples/sample.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
|
2
|
+
require 'keyremac'
|
3
|
+
|
4
|
+
item_ do
|
5
|
+
name_ 'jis_to_us'
|
6
|
+
identifier_ 'private.jis_to_us'
|
7
|
+
autogen_ "__SetKeyboardType__ KeyboardType::MACBOOK"
|
8
|
+
:JIS_YEN .to :BACKQUOTE
|
9
|
+
:JIS_UNDERSCORE .to :BACKQUOTE
|
10
|
+
end
|
11
|
+
|
12
|
+
# semicolonとunderscoreをswap
|
13
|
+
':' .to ':'
|
14
|
+
';' .to '_'
|
15
|
+
'_' .to ';'
|
16
|
+
|
17
|
+
:F7 .to :MUSIC_PREV
|
18
|
+
:F8 .to :MUSIC_PLAY
|
19
|
+
:F9 .to :MUSIC_NEXT
|
20
|
+
:F10 .to :VOLUME_MUTE
|
21
|
+
:F11 .to :VOLUME_DOWN
|
22
|
+
:F12 .to :VOLUME_UP
|
23
|
+
|
24
|
+
:JIS_EISUU .overlaid :COMMAND_L
|
25
|
+
:CONTROL_L .overlaid :CONTROL_L, keys: [:JIS_EISUU, :ESCAPE]
|
26
|
+
:SPACE .overlaid :SHIFT_L, repeat: true
|
27
|
+
|
28
|
+
:m.cmd .to :VK_NONE # disable_minimize
|
29
|
+
:j.ctrl .to :JIS_KANA # "Google IME"
|
30
|
+
:JIS_KANA .to :RETURN
|
31
|
+
:COMMAND_L .to :OPTION_L
|
32
|
+
|
33
|
+
# extra1
|
34
|
+
:SHIFT_L.cmd .to :SHIFT_L.cmd
|
35
|
+
:SHIFT_L.opt .to :SHIFT_L.opt
|
36
|
+
:SHIFT_L.ctrl .to :SHIFT_L.ctrl
|
37
|
+
:CONTROL_L.extra1 .to :CONTROL_L.shift
|
38
|
+
:SHIFT_L .to :VK_MODIFIER_EXTRA1
|
39
|
+
|
40
|
+
# ctrl-npを強制的に↑↓に
|
41
|
+
:p.ctrl.none .to :CURSOR_UP
|
42
|
+
:n.ctrl.none .to :CURSOR_DOWN
|
43
|
+
:b.ctrl.none .to :CURSOR_LEFT
|
44
|
+
:f.ctrl.none .to :CURSOR_RIGHT
|
45
|
+
|
46
|
+
app 'TERMINAL' do
|
47
|
+
"pnco".chars { |c| c.extra1 .to :JIS_EISUU, :t.ctrl, c }
|
48
|
+
"jkl" .chars { |c| c.extra1 .to :JIS_EISUU, :t.ctrl, c }
|
49
|
+
"du" .chars { |c| c.extra1 .to :t.ctrl, '['.ctrl, c.ctrl }
|
50
|
+
end
|
51
|
+
|
52
|
+
appdef_ do
|
53
|
+
appname_ "SUBLIME"
|
54
|
+
equal_ "com.sublimetext.3"
|
55
|
+
equal_ "com.sublimetext.2"
|
56
|
+
end
|
57
|
+
|
58
|
+
['SUBLIME', 'GOOGLE_CHROME'].each { |app_name|
|
59
|
+
app app_name do
|
60
|
+
:p.extra1 .to :JIS_EISUU, '['.cmd.shift
|
61
|
+
:n.extra1 .to :JIS_EISUU, ']'.cmd.shift
|
62
|
+
end
|
63
|
+
}
|
64
|
+
|
65
|
+
app 'SUBLIME', inputsource: 'JAPANESE' do
|
66
|
+
:TAB .to :i.ctrl
|
67
|
+
end
|
data/spec/dump_spec.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'keyremac/base'
|
4
|
+
require 'keyremac/dump'
|
5
|
+
|
6
|
+
module MiniTest::Assertions
|
7
|
+
def assert_xml(expected, rule)
|
8
|
+
xml = Builder::XmlMarkup.new(indent: 2)
|
9
|
+
actual = rule.dump(xml)
|
10
|
+
assert actual == expected, message { diff expected, actual }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
Object.infect_an_assertion :assert_xml, :must_be_xml
|
14
|
+
|
15
|
+
describe 'dump' do
|
16
|
+
before do
|
17
|
+
@root = Keyremac::Root.new
|
18
|
+
@xml = Builder::XmlMarkup.new(indent: 2)
|
19
|
+
Keyremac::Item.reset_identifier
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'rootが出力される' do
|
23
|
+
expected = <<-EOR
|
24
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
25
|
+
<root>
|
26
|
+
<item>
|
27
|
+
<name>root_item</name>
|
28
|
+
<identifier>private.root_item</identifier>
|
29
|
+
</item>
|
30
|
+
</root>
|
31
|
+
EOR
|
32
|
+
@root.must_be_xml expected
|
33
|
+
end
|
34
|
+
|
35
|
+
it '任意のtagを書くことができる' do
|
36
|
+
expected = "<hoge>\n</hoge>\n"
|
37
|
+
@root.hoge_ {}.must_be_xml expected
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'item' do
|
41
|
+
ITEM = <<-EOI
|
42
|
+
<item>
|
43
|
+
<name>a</name>
|
44
|
+
<identifier>private.a</identifier>
|
45
|
+
%s
|
46
|
+
</item>
|
47
|
+
EOI
|
48
|
+
|
49
|
+
it 'blank' do
|
50
|
+
expected = <<-EOI
|
51
|
+
<item>
|
52
|
+
<name>a</name>
|
53
|
+
<identifier>private.a</identifier>
|
54
|
+
</item>
|
55
|
+
EOI
|
56
|
+
@root.item {}.must_be_xml expected
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'raw' do
|
60
|
+
expected = ITEM % "<autogen>__KeyToKey__ KeyCode::J, KeyCode::K</autogen>"
|
61
|
+
@root.item {
|
62
|
+
autogen_ '__KeyToKey__ KeyCode::J, KeyCode::K'
|
63
|
+
}.must_be_xml expected
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'app' do
|
67
|
+
expected = ITEM % "<only>TERMINAL</only>"
|
68
|
+
@root.item(app: 'TERMINAL') {}.must_be_xml expected
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'inputsource' do
|
72
|
+
expected = ITEM % "<inputsource_only>JAPANESE</inputsource_only>"
|
73
|
+
@root.item(inputsource: 'JAPANESE') {}.must_be_xml expected
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe 'app' do
|
78
|
+
it 'raw' do
|
79
|
+
expected = ITEM % "<only>TERMINAL</only>"
|
80
|
+
@root.app('TERMINAL') {}.must_be_xml expected
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe 'to' do
|
85
|
+
it 'basic' do
|
86
|
+
expected = "<autogen>__KeyToKey__ KeyCode::J, KeyCode::K</autogen>\n"
|
87
|
+
(:j .to :k).must_be_xml expected
|
88
|
+
end
|
89
|
+
|
90
|
+
it '複数' do
|
91
|
+
expected = "<autogen>__KeyToKey__ KeyCode::J, KeyCode::K, KeyCode::L</autogen>\n"
|
92
|
+
(:j .to :k, :l).must_be_xml expected
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
ROOT2 = <<-EOR
|
97
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
98
|
+
<root>
|
99
|
+
<item>
|
100
|
+
<name>root_item</name>
|
101
|
+
<identifier>private.root_item</identifier>
|
102
|
+
%s
|
103
|
+
</item>
|
104
|
+
</root>
|
105
|
+
EOR
|
106
|
+
|
107
|
+
describe 'root直下' do
|
108
|
+
it 'root直下にautogenを書くとroot_itemに追加される' do
|
109
|
+
:j .to :k
|
110
|
+
expected = ROOT2 % "<autogen>__KeyToKey__ KeyCode::J, KeyCode::K</autogen>"
|
111
|
+
@root.dump.must_equal expected
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe 'mods' do
|
116
|
+
it 'ctrl' do
|
117
|
+
expected = "KeyCode::J, VK_CONTROL"
|
118
|
+
:j.ctrl.must_be_xml expected
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'none' do
|
122
|
+
expected = "KeyCode::J, ModifierFlag::NONE"
|
123
|
+
:j.none.must_be_xml expected
|
124
|
+
end
|
125
|
+
|
126
|
+
it '複数' do
|
127
|
+
expected = "KeyCode::J, VK_CONTROL | VK_COMMAND"
|
128
|
+
:j.ctrl.cmd.must_be_xml expected
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe 'consumer' do
|
133
|
+
it 'consumer_key' do
|
134
|
+
expected = "ConsumerKeyCode::MUSIC_PREV"
|
135
|
+
:MUSIC_PREV.to_key.must_be_xml expected
|
136
|
+
end
|
137
|
+
it 'key_to_consumer' do
|
138
|
+
expected = "<autogen>__KeyToConsumer__ KeyCode::F7, ConsumerKeyCode::MUSIC_PREV</autogen>\n"
|
139
|
+
(:F7.to:MUSIC_PREV).must_be_xml expected
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe 'key_overlaid_modifier' do
|
144
|
+
it 'basic' do
|
145
|
+
expected = "<autogen>__KeyOverlaidModifier__ KeyCode::JIS_EISUU, KeyCode::COMMAND_L, KeyCode::JIS_EISUU</autogen>\n"
|
146
|
+
(:JIS_EISUU.overlaid:COMMAND_L).must_be_xml expected
|
147
|
+
end
|
148
|
+
it 'keys' do
|
149
|
+
expected = "<autogen>__KeyOverlaidModifier__ KeyCode::CONTROL_L, KeyCode::CONTROL_L, KeyCode::JIS_EISUU, KeyCode::ESCAPE</autogen>\n"
|
150
|
+
autogen = :CONTROL_L .overlaid :CONTROL_L, keys: [:JIS_EISUU, :ESCAPE]
|
151
|
+
autogen.must_be_xml expected
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'repeat' do
|
155
|
+
expected = "<autogen>__KeyOverlaidModifierWithRepeat__ KeyCode::SPACE, KeyCode::SHIFT_L, KeyCode::SPACE</autogen>\n"
|
156
|
+
autogen = :SPACE .overlaid :SHIFT_L, repeat: true
|
157
|
+
autogen.must_be_xml expected
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'keyremac/base'
|
4
|
+
|
5
|
+
describe 'root' do
|
6
|
+
before do
|
7
|
+
@root = Keyremac::Root.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it '末尾に_で任意のtagを書くことができる' do
|
11
|
+
@root.item_ 'hoge'
|
12
|
+
@root.children.length.must_equal 1
|
13
|
+
end
|
14
|
+
|
15
|
+
it '任意のtagはblockで入れ子にできる' do
|
16
|
+
@root.item_ {
|
17
|
+
name_ 'hoge'
|
18
|
+
}
|
19
|
+
@root.children.length.must_equal 1
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'item' do
|
23
|
+
it '' do
|
24
|
+
@root.item {}
|
25
|
+
@root.children.length.must_equal 1
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'raw' do
|
29
|
+
@root.item {
|
30
|
+
autogen_ '__KeyToKey__ KeyCode::J, KeyCode::K'
|
31
|
+
}
|
32
|
+
@root.children.length.must_equal 1
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'app' do
|
36
|
+
@root.item(app: 'TERMINAL') { }
|
37
|
+
@root.children.length.must_equal 1
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'inputsource' do
|
41
|
+
@root.item(inputsource: 'JAPANESE') { }
|
42
|
+
@root.children.length.must_equal 1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'app' do
|
47
|
+
it 'raw' do
|
48
|
+
container = @root.app('dummy') { }
|
49
|
+
container.class.must_equal Keyremac::Item
|
50
|
+
container.children.length.must_equal 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'to' do
|
55
|
+
it 'basic' do
|
56
|
+
item = @root.item {
|
57
|
+
:j .to :k
|
58
|
+
}
|
59
|
+
item.children.length.must_equal 1
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'root直下' do
|
63
|
+
:j .to :k
|
64
|
+
@root.root_item.children.length.must_equal 1
|
65
|
+
end
|
66
|
+
|
67
|
+
it '複数のkeyを渡せる' do
|
68
|
+
:a .to :b, :c
|
69
|
+
@root.root_item.children.length.must_equal 1
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'overlaid' do
|
74
|
+
it 'basic' do
|
75
|
+
item = @root.item {
|
76
|
+
:JIS_EISUU .overlaid :COMMAND_L
|
77
|
+
}
|
78
|
+
item.children.length.must_equal 1
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'basic' do
|
82
|
+
(:JIS_EISUU .overlaid :COMMAND_L).class.must_equal Keyremac::KeyOverlaidModifier
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'keys' do
|
86
|
+
autogen = :CONTROL_L .overlaid :CONTROL_L, keys: [:JIS_EISUU, :ESCAPE]
|
87
|
+
autogen.class.must_equal Keyremac::KeyOverlaidModifier
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'repeat: false' do
|
91
|
+
autogen = :CONTROL_L .overlaid :CONTROL_L
|
92
|
+
autogen.repeat?.must_equal false
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'repeat: true' do
|
96
|
+
autogen = :CONTROL_L .overlaid :CONTROL_L, repeat: true
|
97
|
+
autogen.repeat?.must_equal true
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe 'mods' do
|
102
|
+
[:ctrl, :shift, :opt, :cmd, :extra1].each { |mod|
|
103
|
+
it mod do
|
104
|
+
:j.send(mod).send("#{mod}?").must_equal true
|
105
|
+
end
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
describe 'key' do
|
110
|
+
it '記号を入れると対応するKeyCodeに変換する' do
|
111
|
+
';'.to_key.code.must_equal 'SEMICOLON'
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'shiftが必要なkeyは内部で分解する' do
|
115
|
+
key = :J.to_key
|
116
|
+
key.code.must_equal 'j'
|
117
|
+
key.shift?.must_equal true
|
118
|
+
end
|
119
|
+
|
120
|
+
it '数値を適切にKeyCodeに変換する' do
|
121
|
+
'1'.to_key.code.must_equal 'KEY_1'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe 'consumer_key' do
|
126
|
+
it 'basic' do
|
127
|
+
:MUSIC_PREV.to_key.class.must_equal Keyremac::ConsumerKey
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe 'autogen' do
|
132
|
+
it 'KeyToKey' do
|
133
|
+
(:j .to :k).class.must_equal Keyremac::KeyToKey
|
134
|
+
end
|
135
|
+
it 'KeyToConsumer' do
|
136
|
+
(:F7 .to :MUSIC_PREV).class.must_equal Keyremac::KeyToConsumer
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: keyremac
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- keqh
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: awesome_print
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: builder
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: KeyRemap4MacBook private.xml generator
|
70
|
+
email:
|
71
|
+
- keqh.keqh@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- .travis.yml
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- keyremac.gemspec
|
83
|
+
- lib/keyremac.rb
|
84
|
+
- lib/keyremac/base.rb
|
85
|
+
- lib/keyremac/dump.rb
|
86
|
+
- lib/keyremac/key.rb
|
87
|
+
- lib/keyremac/version.rb
|
88
|
+
- samples/sample.rb
|
89
|
+
- spec/dump_spec.rb
|
90
|
+
- spec/keyremac_spec.rb
|
91
|
+
homepage: ''
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - '>='
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 2.0.2
|
112
|
+
signing_key:
|
113
|
+
specification_version: 4
|
114
|
+
summary: KeyRemap4MacBook private.xml generator
|
115
|
+
test_files:
|
116
|
+
- spec/dump_spec.rb
|
117
|
+
- spec/keyremac_spec.rb
|