fusuma 2.4.1 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +32 -0
  3. data/fusuma.gemspec +17 -18
  4. data/lib/fusuma/config/index.rb +17 -17
  5. data/lib/fusuma/config/searcher.rb +1 -1
  6. data/lib/fusuma/config/yaml_duplication_checker.rb +7 -7
  7. data/lib/fusuma/config.rb +17 -13
  8. data/lib/fusuma/device.rb +12 -12
  9. data/lib/fusuma/environment.rb +10 -10
  10. data/lib/fusuma/hash_support.rb +1 -1
  11. data/lib/fusuma/libinput_command.rb +18 -19
  12. data/lib/fusuma/multi_logger.rb +4 -4
  13. data/lib/fusuma/plugin/base.rb +6 -6
  14. data/lib/fusuma/plugin/buffers/buffer.rb +5 -4
  15. data/lib/fusuma/plugin/buffers/gesture_buffer.rb +6 -6
  16. data/lib/fusuma/plugin/buffers/timer_buffer.rb +2 -2
  17. data/lib/fusuma/plugin/detectors/detector.rb +5 -5
  18. data/lib/fusuma/plugin/detectors/hold_detector.rb +29 -29
  19. data/lib/fusuma/plugin/detectors/pinch_detector.rb +47 -47
  20. data/lib/fusuma/plugin/detectors/rotate_detector.rb +40 -40
  21. data/lib/fusuma/plugin/detectors/swipe_detector.rb +43 -43
  22. data/lib/fusuma/plugin/events/event.rb +11 -11
  23. data/lib/fusuma/plugin/events/records/gesture_record.rb +5 -5
  24. data/lib/fusuma/plugin/events/records/index_record.rb +5 -5
  25. data/lib/fusuma/plugin/events/records/record.rb +2 -2
  26. data/lib/fusuma/plugin/events/records/text_record.rb +1 -1
  27. data/lib/fusuma/plugin/executors/command_executor.rb +4 -4
  28. data/lib/fusuma/plugin/executors/executor.rb +3 -3
  29. data/lib/fusuma/plugin/filters/filter.rb +3 -3
  30. data/lib/fusuma/plugin/filters/libinput_device_filter.rb +12 -12
  31. data/lib/fusuma/plugin/inputs/input.rb +8 -8
  32. data/lib/fusuma/plugin/inputs/libinput_command_input.rb +13 -13
  33. data/lib/fusuma/plugin/inputs/timer_input.rb +3 -3
  34. data/lib/fusuma/plugin/manager.rb +27 -21
  35. data/lib/fusuma/plugin/parsers/libinput_gesture_parser.rb +10 -10
  36. data/lib/fusuma/plugin/parsers/parser.rb +3 -3
  37. data/lib/fusuma/string_support.rb +3 -3
  38. data/lib/fusuma/version.rb +1 -1
  39. data/lib/fusuma.rb +10 -10
  40. metadata +3 -79
  41. data/spec/helpers/config_helper.rb +0 -20
  42. data/spec/lib/config/searcher_spec.rb +0 -179
  43. data/spec/lib/config_spec.rb +0 -104
  44. data/spec/lib/custom_process_spec.rb +0 -29
  45. data/spec/lib/device_spec.rb +0 -96
  46. data/spec/lib/dummy_config.yml +0 -31
  47. data/spec/lib/fusuma_spec.rb +0 -103
  48. data/spec/lib/libinput-list-devices_iberianpig-XPS-9360.txt +0 -181
  49. data/spec/lib/libinput-list-devices_magic_trackpad.txt +0 -51
  50. data/spec/lib/libinput-list-devices_razer_razer_blade.txt +0 -252
  51. data/spec/lib/libinput-list-devices_thejinx0r.txt +0 -361
  52. data/spec/lib/libinput-list-devices_unavailable.txt +0 -36
  53. data/spec/lib/libinput_command_spec.rb +0 -164
  54. data/spec/lib/plugin/base_spec.rb +0 -74
  55. data/spec/lib/plugin/buffers/buffer_spec.rb +0 -80
  56. data/spec/lib/plugin/buffers/dummy_buffer.rb +0 -20
  57. data/spec/lib/plugin/buffers/gesture_buffer_spec.rb +0 -192
  58. data/spec/lib/plugin/detectors/detector_spec.rb +0 -43
  59. data/spec/lib/plugin/detectors/dummy_detector.rb +0 -24
  60. data/spec/lib/plugin/detectors/hold_detector_spec.rb +0 -145
  61. data/spec/lib/plugin/detectors/pinch_detector_spec.rb +0 -119
  62. data/spec/lib/plugin/detectors/rotate_detector_spec.rb +0 -125
  63. data/spec/lib/plugin/detectors/swipe_detector_spec.rb +0 -118
  64. data/spec/lib/plugin/events/event_spec.rb +0 -30
  65. data/spec/lib/plugin/events/records/gesture_record_spec.rb +0 -22
  66. data/spec/lib/plugin/events/records/record_spec.rb +0 -31
  67. data/spec/lib/plugin/events/records/text_record_spec.rb +0 -26
  68. data/spec/lib/plugin/executors/command_executor_spec.rb +0 -57
  69. data/spec/lib/plugin/executors/executor_spec.rb +0 -164
  70. data/spec/lib/plugin/filters/filter_spec.rb +0 -92
  71. data/spec/lib/plugin/filters/libinput_filter_spec.rb +0 -120
  72. data/spec/lib/plugin/inputs/input_spec.rb +0 -70
  73. data/spec/lib/plugin/inputs/libinput_command_input_spec.rb +0 -121
  74. data/spec/lib/plugin/inputs/timer_input_spec.rb +0 -40
  75. data/spec/lib/plugin/manager_spec.rb +0 -27
  76. data/spec/lib/plugin/parsers/libinput_gesture_parser_spec.rb +0 -76
  77. data/spec/lib/plugin/parsers/parser_spec.rb +0 -45
  78. data/spec/spec_helper.rb +0 -23
@@ -1,179 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
- require './lib/fusuma/config'
5
- require './lib/fusuma/config/searcher'
6
-
7
- # spec for Config
8
- module Fusuma
9
- RSpec.describe Config::Searcher do
10
- around do |example|
11
- ConfigHelper.load_config_yml = <<~CONFIG
12
- swipe:
13
- 3:
14
- left:
15
- command: 'alt+Left'
16
- right:
17
- command: 'alt+Right'
18
- 4:
19
- left:
20
- command: 'super+Left'
21
- right:
22
- command: 'super+Right'
23
- pinch:
24
- in:
25
- command: 'ctrl+plus'
26
- out:
27
- command: 'ctrl+minus'
28
- CONFIG
29
-
30
- example.run
31
-
32
- ConfigHelper.clear_config_yml
33
- end
34
-
35
- describe '.search' do
36
- let(:index) { nil }
37
- let(:location) { Config.instance.keymap[0] }
38
- let(:search) { Config::Searcher.new.search(index, location: location) }
39
- context 'index correct order' do
40
- let(:index) { Config::Index.new %w[pinch in command] }
41
- it { expect(Config::Searcher.new.search(index, location: location)).to eq 'ctrl+plus' }
42
- end
43
-
44
- context 'index incorrect order' do
45
- let(:index) { Config::Index.new %w[in pinch 2 command] }
46
- it { expect(Config::Searcher.new.search(index, location: location)).not_to eq 'ctrl+plus' }
47
- end
48
-
49
- context 'with Skip condtions' do
50
- context 'when index includes skippable key' do
51
- let(:index) do
52
- Config::Index.new [
53
- Config::Index::Key.new('pinch'),
54
- Config::Index::Key.new(2, skippable: true),
55
- Config::Index::Key.new('out'),
56
- Config::Index::Key.new('command')
57
- ]
58
- end
59
- it 'detects ctrl+minus with skip' do
60
- condition, value = Config::Searcher.find_condition do
61
- Config::Searcher.new.search(index, location: location)
62
- end
63
- expect([condition, value]).to eq([:skip, 'ctrl+minus'])
64
- end
65
- end
66
-
67
- context 'when index includes skippable key at first' do
68
- let(:index) do
69
- Config::Index.new [
70
- Config::Index::Key.new(:hoge, skippable: true),
71
- Config::Index::Key.new(:fuga, skippable: true),
72
- Config::Index::Key.new('pinch'),
73
- Config::Index::Key.new('in'),
74
- Config::Index::Key.new(:piyo, skippable: true),
75
- Config::Index::Key.new('command')
76
- ]
77
- end
78
- it 'detects ctrl+plus with skip' do
79
- condition, value = Config::Searcher.find_condition do
80
- Config::Searcher.new.search(index, location: location)
81
- end
82
- expect([condition, value]).to eq([:skip, 'ctrl+plus'])
83
- end
84
- end
85
-
86
- context 'with begin/update/end' do
87
- around do |example|
88
- ConfigHelper.load_config_yml = <<~CONFIG
89
- swipe:
90
- 3:
91
- begin:
92
- command: 'echo begin'
93
- update:
94
- command: 'echo update'
95
- end:
96
- command: 'echo end'
97
- keypress:
98
- LEFTCTRL:
99
- command: 'echo end+ctrl'
100
- CONFIG
101
-
102
- example.run
103
-
104
- ConfigHelper.clear_config_yml
105
- end
106
-
107
- context 'without keypress' do
108
- let(:index) do
109
- Config::Index.new [
110
- Config::Index::Key.new(:swipe),
111
- Config::Index::Key.new(3),
112
- Config::Index::Key.new('left', skippable: true),
113
- Config::Index::Key.new('end'),
114
- Config::Index::Key.new('command')
115
- ]
116
- end
117
-
118
- it 'detects with skip' do
119
- condition, value = Config::Searcher.find_condition do
120
- Config::Searcher.new.search(index, location: location)
121
- end
122
- expect([condition, value]).to eq([:skip, 'echo end'])
123
- end
124
- end
125
- context 'with keypress' do
126
- context 'with valid key existing in config.yml' do
127
- let(:index) do
128
- Config::Index.new [
129
- Config::Index::Key.new(:swipe),
130
- Config::Index::Key.new(3),
131
- Config::Index::Key.new('left', skippable: true),
132
- Config::Index::Key.new('end'),
133
- Config::Index::Key.new('keypress', skippable: true),
134
- Config::Index::Key.new('LEFTCTRL', skippable: true),
135
- Config::Index::Key.new('command')
136
- ]
137
- end
138
- it 'detects end+ctrl with skip' do
139
- condition, value = Config::Searcher.find_condition do
140
- Config::Searcher.new.search(index, location: location)
141
- end
142
- expect([condition, value]).to eq([:skip, 'echo end+ctrl'])
143
- end
144
- end
145
- context 'with non-existing key not existing in config.yml' do
146
- let(:index) do
147
- Config::Index.new [
148
- Config::Index::Key.new(:swipe),
149
- Config::Index::Key.new(3),
150
- Config::Index::Key.new('up', skippable: true),
151
- Config::Index::Key.new('end'),
152
- Config::Index::Key.new('keypress', skippable: true),
153
- Config::Index::Key.new('LEFTSHIFT', skippable: true), # Invalid key
154
- Config::Index::Key.new('command')
155
- ]
156
- end
157
- it 'detects end with skip (fallback to no keypress)' do
158
- condition, value = Config::Searcher.find_condition do
159
- Config::Searcher.new.search(index, location: location)
160
- end
161
- expect([condition, value]).to eq([:skip, 'echo end'])
162
- end
163
- end
164
- end
165
- end
166
- end
167
- end
168
-
169
- describe 'private_method: :cache' do
170
- it 'should cache command' do
171
- key = %w[event_type finger direction command].join(',')
172
- value = 'shourtcut string'
173
- searcher = Config::Searcher.new
174
- searcher.send(:cache, key) { value }
175
- expect(searcher.send(:cache, key)).to eq value
176
- end
177
- end
178
- end
179
- end
@@ -1,104 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
- require './lib/fusuma/config'
5
-
6
- # spec for Config
7
- module Fusuma
8
- RSpec.describe Config do
9
- let(:keymap) do
10
- {
11
- 'swipe' => {
12
- 3 => {
13
- 'left' => { 'command' => 'alt+Left' },
14
- 'right' => { 'command' => 'alt+Right' }
15
- },
16
- 4 => {
17
- 'left' => { 'command' => 'super+Left' },
18
- 'right' => { 'command' => 'super+Right' }
19
- }
20
- },
21
- 'pinch' => {
22
- 'in' => { 'command' => 'ctrl+plus' },
23
- 'out' => { 'command' => 'ctrl+minus' }
24
- }
25
- }
26
- end
27
-
28
- describe '.custom_path=' do
29
- before { Singleton.__init__(Config) }
30
- it 'should reload keymap file' do
31
- keymap = Config.instance.keymap
32
- Config.custom_path = './spec/lib/dummy_config.yml'
33
- custom_keymap = Config.instance.keymap
34
- expect(keymap).not_to eq custom_keymap
35
- end
36
- end
37
-
38
- describe '#reload' do
39
- before { Singleton.__init__(Config) }
40
- it 'set Seacher' do
41
- old = Config.instance.searcher
42
- Config.instance.reload
43
- expect(Config.instance.searcher).not_to eq(old)
44
- end
45
- end
46
-
47
- describe '#validate' do
48
- context 'with valid yaml' do
49
- before do
50
- string = <<~CONFIG
51
- swipe:
52
- 3:
53
- left:
54
- command: echo 'swipe left'
55
-
56
- CONFIG
57
- @file_path = Tempfile.open do |temp_file|
58
- temp_file.tap { |f| f.write(string) }
59
- end
60
- end
61
-
62
- it 'should return Hash' do
63
- Config.instance.validate(@file_path)
64
- end
65
- end
66
-
67
- context 'with invalid yaml' do
68
- before do
69
- string = <<~CONFIG
70
- this is not yaml
71
- CONFIG
72
- @file_path = Tempfile.open do |temp_file|
73
- temp_file.tap { |f| f.write(string) }
74
- end
75
- end
76
-
77
- it 'raise InvalidFileError' do
78
- expect { Config.instance.validate(@file_path) }.to raise_error(Config::InvalidFileError)
79
- end
80
-
81
- context 'with duplicated key' do
82
- before do
83
- string = <<~CONFIG
84
- pinch:
85
- 2:
86
- in:
87
- command: "xdotool keydown ctrl click 4 keyup ctrl" # threshold: 0.5, interval: 0.5
88
- 2:
89
- out:
90
- command: "xdotool keydown ctrl click 5 keyup ctrl" # threshold: 0.5, interval: 0.5
91
- CONFIG
92
- @file_path = Tempfile.open do |temp_file|
93
- temp_file.tap { |f| f.write(string) }
94
- end
95
- end
96
-
97
- it 'raise InvalidFileError' do
98
- expect { Config.instance.validate(@file_path) }.to raise_error(Config::InvalidFileError)
99
- end
100
- end
101
- end
102
- end
103
- end
104
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
- require './lib/fusuma/custom_process'
5
-
6
- module Fusuma
7
- RSpec.describe CustomProcess do
8
- class ForkTest
9
- include CustomProcess
10
-
11
- def call
12
- fork { puts 'hoge' }
13
- end
14
- end
15
-
16
- describe '.fork' do
17
- before do
18
- @test_instance = ForkTest.new
19
- end
20
- it 'call Process.fork and Process.setproctitle' do
21
- expect(Process).to receive(:fork).and_yield do |block_context|
22
- allow(block_context).to receive(:proctitle).and_return(@test_instance.proctitle)
23
- expect(Process).to receive(:setproctitle).with(@test_instance.proctitle)
24
- end
25
- @test_instance.call
26
- end
27
- end
28
- end
29
- end
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
- require './lib/fusuma/device'
5
- require './lib/fusuma/plugin/inputs/libinput_command_input'
6
-
7
- module Fusuma
8
- RSpec.describe Device do
9
- describe '.all' do
10
- it 'should fetch all devices'
11
- end
12
-
13
- describe '.reset' do
14
- it 'should clear all cache'
15
- end
16
-
17
- describe '.available' do
18
- let(:libinput_device_command) { 'dummy-libinput-list-devices' }
19
-
20
- before do
21
- Device.reset
22
- allow_any_instance_of(LibinputCommand)
23
- .to receive(:list_devices_command)
24
- .and_return(libinput_device_command)
25
-
26
- @dummy_io = StringIO.new('dummy')
27
- allow(Open3).to receive(:popen3)
28
- .with(libinput_device_command)
29
- .and_return([@dummy_io, list_devices_output, @dummy_io, nil])
30
- end
31
-
32
- context 'with XPS-9360 (have a correct device)' do
33
- let(:list_devices_output) do
34
- File.open('./spec/lib/libinput-list-devices_iberianpig-XPS-9360.txt')
35
- end
36
-
37
- it { expect(Device.available).to be_a Array }
38
- it { expect(Device.available.map(&:name)).not_to include 'Power Button' }
39
- it { expect(Device.available.map(&:name)).to include 'DLL075B:01 06CB:76AF Touchpad' }
40
- end
41
-
42
- context 'with no tap to click device (like a bluetooth apple trackpad)' do
43
- let(:list_devices_output) do
44
- File.open('spec/lib/libinput-list-devices_magic_trackpad.txt')
45
- end
46
-
47
- it { expect(Device.available).to be_a Array }
48
- it { expect(Device.available.map(&:name)).to eq ['Christopher’s Trackpad', 'bcm5974'] }
49
- end
50
-
51
- context "context with the device's name not found at first line" do
52
- let(:list_devices_output) do
53
- File.open('spec/lib/libinput-list-devices_thejinx0r.txt')
54
- end
55
-
56
- it { expect(Device.available).to be_a Array }
57
- it { expect(Device.available.map(&:name)).to include 'HTX USB HID Device HTX HID Device Touchpad' }
58
- end
59
-
60
- context 'when no devices' do
61
- let(:list_devices_output) do
62
- File.open('spec/lib/libinput-list-devices_unavailable.txt')
63
- end
64
-
65
- it 'should failed with exit' do
66
- expect { Device.available }.to raise_error(SystemExit)
67
- end
68
-
69
- it 'should failed with printing error log' do
70
- expect(MultiLogger).to receive(:error)
71
- expect { Device.available }.to raise_error(SystemExit)
72
- end
73
- end
74
-
75
- context 'with some device has same names' do
76
- let(:list_devices_output) do
77
- File.open('spec/lib/libinput-list-devices_razer_razer_blade.txt')
78
- end
79
-
80
- it { expect(Device.available).to be_a Array }
81
- it 'should have capabilities' do
82
- razer_devices = Device.all.group_by(&:name)['Razer Razer Blade']
83
- expect(razer_devices.size).to eq 3
84
- end
85
-
86
- it 'should know capabilities' do
87
- razer_devices = Device.all.group_by(&:name)['Razer Razer Blade']
88
- capabilities = razer_devices.map(&:capabilities)
89
- expect(capabilities).to eq ['keyboard', 'keyboard pointer', 'pointer']
90
- keyboard_devices = razer_devices.select { |d| d.capabilities == 'keyboard' }
91
- expect(keyboard_devices.size).to eq 1
92
- end
93
- end
94
- end
95
- end
96
- end
@@ -1,31 +0,0 @@
1
- swipe:
2
- 3:
3
- left:
4
- command: 'echo swipe 3 left'
5
- right:
6
- command: 'echo swipe 3 right'
7
- up:
8
- command: 'echo swipe 3 up'
9
- down:
10
- command: 'echo swipe 3 down'
11
- 4:
12
- left:
13
- command: 'echo swipe 4 left'
14
- right:
15
- command: 'echo swipe 4 right'
16
- up:
17
- command: 'echo swipe 4 up'
18
- down:
19
- command: 'echo swipe 4 down'
20
-
21
- pinch:
22
- 2:
23
- in:
24
- command: 'echo pinch 2 in'
25
- out:
26
- command: 'echo pinch 2 out'
27
- 4:
28
- in:
29
- command: 'echo pinch 4 in'
30
- out:
31
- command: 'echo pinch 4 in'
@@ -1,103 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
- require './lib/fusuma'
5
- require './lib/fusuma/plugin/inputs/libinput_command_input'
6
- require './lib/fusuma/plugin/filters/libinput_device_filter'
7
-
8
- module Fusuma
9
- RSpec.describe Runner do
10
- describe '.run' do
11
- before do
12
- Singleton.__init__(MultiLogger)
13
- Singleton.__init__(Config)
14
- allow_any_instance_of(Runner).to receive(:run)
15
- allow_any_instance_of(LibinputCommand).to receive(:version)
16
- .and_return("1.8\n")
17
- end
18
-
19
- context 'when without option' do
20
- it 'should not enable debug mode' do
21
- expect(MultiLogger.instance).not_to be_debug_mode
22
- Runner.run
23
- end
24
- end
25
-
26
- context 'when run with argument "--version"' do
27
- # NOTE: skip print reload config message
28
- before { allow(MultiLogger).to receive(:info).with(anything) }
29
- it 'should print version' do
30
- expect(MultiLogger).to receive(:info)
31
- .with("Fusuma: #{Fusuma::VERSION}")
32
- expect(MultiLogger).to receive(:info)
33
- .with("libinput: #{LibinputCommand.new.version}")
34
- expect(MultiLogger).to receive(:info)
35
- .with("OS: #{`uname -rsv`}".strip)
36
- expect(MultiLogger).to receive(:info)
37
- .with("Distribution: #{`cat /etc/issue`}".strip)
38
- expect(MultiLogger).to receive(:info)
39
- .with("Desktop session: #{`echo $DESKTOP_SESSION $XDG_SESSION_TYPE`}".strip)
40
- expect { Runner.run(version: true) }.to raise_error(SystemExit)
41
- end
42
- end
43
-
44
- context 'when run with argument "-l"' do
45
- it 'should print device list' do
46
- allow(Device).to receive(:available) {
47
- [
48
- Device.new(name: 'test_device1'),
49
- Device.new(name: 'test_device2')
50
- ]
51
- }
52
-
53
- expected = <<~OUTPUT
54
- test_device1
55
- test_device2
56
- OUTPUT
57
- expect { Runner.run(list: true) }.to raise_error(SystemExit)
58
- .and output(/#{expected}/).to_stdout
59
- end
60
- end
61
-
62
- # TODO: remove from_option and command line options
63
- context 'when run with argument "--device="test_device2"' do
64
- it 'should set device' do
65
- allow(Device).to receive(:names) { %w[test_device1 test_device2] }
66
- expect(Plugin::Filters::LibinputDeviceFilter::KeepDevice)
67
- .to receive(:from_option=).with('test_device2')
68
- Runner.run(device: 'test_device2')
69
- end
70
- end
71
-
72
- context 'when run with argument "-v"' do
73
- it 'should enable debug mode' do
74
- MultiLogger.send(:new)
75
- Runner.run(verbose: true)
76
- expect(MultiLogger.instance).to be_debug_mode
77
- end
78
- end
79
-
80
- context 'when run with argument "-c path/to/config.yml"' do
81
- before do
82
- allow_any_instance_of(Runner).to receive(:run)
83
- @config = Config.instance
84
-
85
- string = <<~CONFIG
86
- swipe:
87
- 3:
88
- left:
89
- command: echo 'swipe left'
90
-
91
- CONFIG
92
- @file_path = Tempfile.open do |temp_file|
93
- temp_file.tap { |f| f.write(string) }
94
- end
95
- end
96
- it 'should assign custom_path' do
97
- expect { Runner.run(config_path: @file_path) }
98
- .to change { @config.custom_path }.from(nil).to(@file_path)
99
- end
100
- end
101
- end
102
- end
103
- end