rkremap 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6476d10293c91c5afb744c6ebe1162d26ab253ad06aade6f5f2568db05bb7631
4
- data.tar.gz: 35fd73d5a2d71ca797fd626397a789e8f22b5bd54cfa2ef0ca08f46adc6efa7f
3
+ metadata.gz: 2052faf03d55e5ca684ee7c991fe42ecb187f2294376216e333d9aced2a45188
4
+ data.tar.gz: cc901a01fec47fcafc320ea355c5ea71dd8cc8e54c05f4f7774f02beda3ab328
5
5
  SHA512:
6
- metadata.gz: bdf4f1364db8aa24dc49dab823e4f16200994058a6ff8d8e3323272d0783139af49f6fcdbb7f22b573dab92554d39d92429d24aa7b5fedf80e27139cf62bd120
7
- data.tar.gz: d868e6b7af37edfa90324014669ff7de5595f392116bedeaf011cf95cd49ce9621782f1dda6e402c4e6117509ae0a0337322447028975ab743324da318479d0b
6
+ metadata.gz: dad24b3679af4213746a787811812afe8791d4964eba2ea018debffb94f7558dec29915a9be18e3aa1952a6817ea6ec823045c0ab8ae45afc9d22649f8c90374
7
+ data.tar.gz: 6dbef790e758293b32891d2aabd4cc939b3259b55b5c6d5ed297d2a96ffe9feaeb657675c98b16cd3c73480f3d6f0b35e98f12fadd0d0f41a3020cca894cf069
data/README.md CHANGED
@@ -79,6 +79,44 @@ rkremap.exclude = /touchpad/i
79
79
  `true` の場合はキーボードデバイスの接続を自動検知する。
80
80
  `new` 時にデバイスファイルが指定されない場合は `true` になる。
81
81
 
82
+ ### Rkremap#remap
83
+
84
+ 引数の Hash で変換するキーを指定する:
85
+ ```ruby
86
+ rk.remap(KEY_CAPSLOCK => KEY_LEFTCTRL)
87
+ ```
88
+
89
+ 変換元を配列で修飾キーを書くとその修飾キーとの組み合わせで変換する:
90
+ ```ruby
91
+ rk.remap([KEY_LEFTCTRL, KEY_A] => KEY_HOME)
92
+ ```
93
+
94
+ hold を指定すると指定秒数長押ししたときだけ変換する:
95
+ ```ruby
96
+ rk.remap(hold: 0.5, map: {
97
+ KEY_MUHENKAN => KEY_RIGHTMETA,
98
+ KEY_HENKAN => KEY_RIGHTMETA,
99
+ })
100
+ ```
101
+
102
+ 次のように書くと、A も B も C もすべて A になってしまう:
103
+ ```ruby
104
+ rk.remap(KEY_A => KEY_B)
105
+ rk.remap(KEY_B => KEY_C)
106
+ rk.remap(KEY_C => KEY_A)
107
+ ```
108
+
109
+ A を B, B を C, C を A と変換したい場合は次のように書く:
110
+ ```ruby
111
+ rk.remap(
112
+ KEY_A => KEY_B,
113
+ KEY_B => KEY_C,
114
+ KEY_C => KEY_A
115
+ )
116
+ ```
117
+
118
+ `#remap` で実現できないような複雑な処理は、後述の `#match` や `#start` で書くことができるかもしれない。
119
+
82
120
  ### Rkremap#start
83
121
 
84
122
  なにかキーを押されたらブロックを実行する。修飾キー単体ではブロックは実行されない。
@@ -2,51 +2,24 @@
2
2
  # 0.5秒以内でも変換/無変換キーを押しながら他のキーを押すとSUPERキーとして扱う。
3
3
 
4
4
  require 'rkremap'
5
- require 'tmtms_timer'
6
5
 
7
6
  include Rkremap::KeyCode
8
7
 
9
- rk = Rkremap.new
8
+ rk = Rkremap.new(*ARGV, mouse: true)
10
9
  rk.grab = true
11
10
 
12
- timer = Tmtms::Timer.new
13
- jobs = {
14
- KEY_HENKAN => nil,
15
- KEY_MUHENKAN => nil,
16
- }
17
-
18
- henkan_map = {
11
+ # HENKAN, MUHENKAN を 0.5秒以上押したら SUPER とする
12
+ rk.remap(hold: 0.5, map: {
19
13
  KEY_HENKAN => KEY_RIGHTMETA,
20
14
  KEY_MUHENKAN => KEY_RIGHTMETA, # LEFTMETA だとデスクトップ環境のメニューが開いたりするため
21
- }
15
+ })
22
16
 
23
- rk.match(code: [KEY_HENKAN, KEY_MUHENKAN]) do |event|
24
- if event.type == :press
25
- job = timer.set(0.5) do
26
- rk.synchronize do
27
- rk.event(code: henkan_map[event.code], type: :press)
28
- end
29
- end
30
- jobs[event.code] = job
31
- elsif event.type == :release
32
- if jobs[event.code]&.cancel # 0.5秒以内に離された
33
- rk.key(event.code)
34
- else
35
- rk.event(code: henkan_map[event.code], type: :release)
36
- end
37
- end
17
+ # マウスボタンイベントはそのまま
18
+ rk.match(device: :mouse) do |event|
19
+ rk.event(code: event.code, type: event.type)
38
20
  event.skip
39
21
  end
40
22
 
41
- # 何かキーが押されたときに HENKAN, MUHENKAN が押されてれば SUPER が押されてることにする
42
- rk.match(type: :press) do
43
- [KEY_HENKAN, KEY_MUHENKAN].each do |code|
44
- if jobs[code]&.cancel # 0.5秒以内
45
- rk.event(code: henkan_map[code], type: :press)
46
- end
47
- end
48
- end
49
-
50
23
  rk.start do |code, mod|
51
24
  rk.key(code, mod)
52
25
  end
data/example/tmtms.rb CHANGED
@@ -1,57 +1,22 @@
1
1
  # tmtms 用
2
2
 
3
3
  require 'rkremap'
4
- require 'tmtms_timer'
5
4
 
6
5
  include Rkremap::KeyCode
7
6
 
8
- rk = Rkremap.new(*ARGV, mouse: true, exclude: /touchpad/i)
7
+ rk = Rkremap.new(*ARGV, mouse: true, exclude: /\AELAN0676/i)
9
8
  rk.grab = true
10
9
  rk.x11 = true
11
10
 
12
- until system "xinput | grep -q rkremap"
13
- sleep 0.1
14
- end
11
+ # rkremap がシステムに認識されたら中ボタンスクロールを有効にする
12
+ sleep 0.1 until system "xinput | grep -q rkremap"
15
13
  system "xinput set-prop pointer:rkremap 'libinput Scroll Method Enabled' 0 0 1"
16
14
 
17
15
  # HENKAN, MUHENKAN を 0.5秒以上押したら SUPER とする
18
- timer = Tmtms::Timer.new
19
- jobs = {
20
- KEY_HENKAN => nil,
21
- KEY_MUHENKAN => nil,
22
- }
23
-
24
- henkan_map = {
16
+ rk.remap(hold: 0.5, map: {
25
17
  KEY_HENKAN => KEY_RIGHTMETA,
26
18
  KEY_MUHENKAN => KEY_RIGHTMETA, # LEFTMETA だとデスクトップ環境のメニューが開いたりするため
27
- }
28
-
29
- rk.match(code: [KEY_HENKAN, KEY_MUHENKAN]) do |event|
30
- if event.type == :press
31
- job = timer.set(0.5) do
32
- rk.synchronize do
33
- rk.event(code: henkan_map[event.code], type: :press)
34
- end
35
- end
36
- jobs[event.code] = job
37
- elsif event.type == :release
38
- if jobs[event.code]&.cancel # 0.5秒以内に離された
39
- rk.key(event.code)
40
- else
41
- rk.event(code: henkan_map[event.code], type: :release)
42
- end
43
- end
44
- event.skip
45
- end
46
-
47
- # 何かキーが押されたときに HENKAN, MUHENKAN が押されてれば SUPER が押されてることにする
48
- rk.match(type: :press) do
49
- [KEY_HENKAN, KEY_MUHENKAN].each do |code|
50
- if jobs[code]&.cancel # 0.5秒以内
51
- rk.event(code: henkan_map[code], type: :press)
52
- end
53
- end
54
- end
19
+ })
55
20
 
56
21
  # マウスボタンイベントはそのまま
57
22
  rk.match(device: :mouse) do |event|
@@ -60,9 +25,17 @@ rk.match(device: :mouse) do |event|
60
25
  end
61
26
 
62
27
  # CAPSLOCK は CTRL に変換
63
- rk.match(code: KEY_CAPSLOCK) do |event|
64
- event.code = KEY_LEFTCTRL
65
- end
28
+ rk.remap(KEY_CAPSLOCK => KEY_LEFTCTRL)
29
+
30
+ # JISキーボードを英語配列にしたときに一部キーを変える
31
+ rk.remap(
32
+ KEY_YEN => KEY_BACKSLASH,
33
+ KEY_BACKSLASH => KEY_GRAVE,
34
+ KEY_GRAVE => KEY_ESC,
35
+ [KEY_LEFTSHIFT, KEY_RO] => [KEY_LEFTSHIFT, KEY_MINUS],
36
+ [KEY_RIGHTSHIFT, KEY_RO] => [KEY_LEFTSHIFT, KEY_MINUS],
37
+ KEY_RO => KEY_BACKSLASH,
38
+ )
66
39
 
67
40
  mod_disable_ctrl = {
68
41
  KEY_LEFTCTRL => false,
@@ -82,20 +55,6 @@ mod_disable_meta = {
82
55
  }
83
56
  mod_disable_all = {}.merge(mod_disable_ctrl, mod_disable_shift, mod_disable_alt, mod_disable_meta)
84
57
 
85
- # JISキーボードを英語配列にしたときに一部キーを変える
86
- key_map = {
87
- KEY_YEN => KEY_BACKSLASH,
88
- KEY_BACKSLASH => KEY_GRAVE,
89
- KEY_GRAVE => KEY_ESC,
90
- }
91
- rk.match do |event, mod|
92
- event.code = key_map[event.code] || event.code
93
- # RO キーは「\」(SHIFTキーを押してる場合は「_」)
94
- if event.code == KEY_RO
95
- event.code = (mod[KEY_LEFTSHIFT] || mod[KEY_RIGHTSHIFT]) ? KEY_MINUS : KEY_BACKSLASH
96
- end
97
- end
98
-
99
58
  # Emacs や VirtualBox ではそのまま
100
59
  rk.match(app: /Emacs|VirtualBox Machine/) do |event|
101
60
  rk.event(code: event.code, type: event.type)
@@ -0,0 +1,105 @@
1
+ class Rkremap
2
+ class Remap
3
+ # @param map [Hash] from => to
4
+ # @param hold [Numeric] seconds
5
+ def initialize(rk, map:, hold:)
6
+ @rk = rk
7
+ @pressed = {}
8
+
9
+ if hold
10
+ setup_holding_event(map, hold)
11
+ else
12
+ setup_event(map)
13
+ end
14
+ end
15
+
16
+ # @param map [Hash] {form => to}
17
+ def setup_event(map)
18
+ keycodes = map.keys.flatten
19
+
20
+ @rk.match(code: keycodes, type: :press) do |event, current_mod|
21
+ map.each do |from, to|
22
+ if event_match?(from, event, current_mod)
23
+ make_press_event(to, event)
24
+ break
25
+ end
26
+ end
27
+ end
28
+
29
+ @rk.match(code: keycodes, type: :release) do |event|
30
+ if @pressed[event.code]
31
+ @rk.event(code: @pressed[event.code], type: :release)
32
+ @pressed[event.code] = nil
33
+ event.skip
34
+ end
35
+ end
36
+ end
37
+
38
+ # @param map [Hash] {form => to}
39
+ # @param hold [Numeric] seconds
40
+ def setup_holding_event(map, hold)
41
+ keycodes = map.keys.flatten
42
+ timer = Tmtms::Timer.new
43
+ jobs = map.transform_values{nil}
44
+
45
+ @rk.match(code: keycodes, type: :press) do |event|
46
+ map.each do |from, to|
47
+ if from == event.code
48
+ jobs[event.code] = timer.set(hold) do
49
+ @rk.synchronize{ make_press_event(to) }
50
+ end
51
+ event.skip
52
+ break
53
+ end
54
+ end
55
+ end
56
+
57
+ @rk.match(code: keycodes, type: :repeat) do |event|
58
+ event.skip
59
+ end
60
+
61
+ @rk.match(code: keycodes, type: :release) do |event|
62
+ if jobs[event.code]&.cancel
63
+ @rk.key(event.code)
64
+ elsif map[event.code]
65
+ @rk.event(code: map[event.code], type: :release)
66
+ end
67
+ event.skip
68
+ end
69
+
70
+ @rk.match(type: :press) do
71
+ jobs.each do |code, job|
72
+ make_press_event(map[code]) if job&.cancel
73
+ end
74
+ end
75
+ end
76
+
77
+ # @param keys [Integer, Array<Integer>] KEY_A, [KEY_LEFTCTRL, KEY_A], [:SHIFT, KEY_A], ...
78
+ # @param event [Rkremap::Event]
79
+ # @param mod [Hash] current modifiers status
80
+ def event_match?(keys, event, mod)
81
+ if keys == event.code
82
+ return true
83
+ end
84
+ keys = Array(keys)
85
+ return false unless keys.include? event.code
86
+ (keys - [event.code]).all?{mod[_1]}
87
+ end
88
+
89
+ # @param to [Integer, Array<Integer>]
90
+ # @param event [Rkremap::Event, nil]
91
+ def make_press_event(to, event=nil)
92
+ Array(to).each do |key|
93
+ @pressed[event.code] = key if event
94
+ if @rk.modifiers.include? key
95
+ @rk.event(code: key, type: :press)
96
+ event&.skip
97
+ elsif event
98
+ event.code = key
99
+ else
100
+ @rk.key(code: key, type: :press)
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Rkremap
4
- VERSION = "0.4.1"
4
+ VERSION = "0.5.0"
5
5
  end
data/lib/rkremap.rb CHANGED
@@ -7,6 +7,7 @@ require_relative 'rkremap/evdev_list'
7
7
  require_relative 'rkremap/evdev'
8
8
  require_relative 'rkremap/event'
9
9
  require_relative 'rkremap/uinput'
10
+ require_relative 'rkremap/remap'
10
11
 
11
12
  class Rkremap
12
13
  include KeyCode
@@ -57,6 +58,17 @@ class Rkremap
57
58
  @mutex = Mutex.new
58
59
  end
59
60
 
61
+ # @overload remap(map)
62
+ # @param map [Hash] from => to
63
+ # @overload remap(map:, hold: nil)
64
+ # @param map [Hash] from => to
65
+ # @param hold [Numeric] seconds
66
+ def remap(**opts)
67
+ map, hold = opts[:map], opts[:hold]
68
+ map ||= opts
69
+ Remap.new(self, map: map, hold: hold)
70
+ end
71
+
60
72
  # @param device [Symbol, Regexp]
61
73
  # @param code [Integer]
62
74
  # @param type [Symbol] :press / :release / :repeat
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rkremap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - TOMITA Masahiro
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-08-27 00:00:00.000000000 Z
11
+ date: 2022-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tmtms_timer
@@ -41,6 +41,7 @@ files:
41
41
  - lib/rkremap/evdev_list.rb
42
42
  - lib/rkremap/event.rb
43
43
  - lib/rkremap/keycode.rb
44
+ - lib/rkremap/remap.rb
44
45
  - lib/rkremap/uinput.rb
45
46
  - lib/rkremap/version.rb
46
47
  - lib/rkremap/winattr.rb