fusuma 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fusuma/plugin/manager.rb +3 -3
  3. data/lib/fusuma/version.rb +1 -1
  4. data/spec/helpers/config_helper.rb +20 -0
  5. data/spec/lib/config/searcher_spec.rb +97 -0
  6. data/spec/lib/config_spec.rb +112 -0
  7. data/spec/lib/custom_process_spec.rb +28 -0
  8. data/spec/lib/device_spec.rb +98 -0
  9. data/spec/lib/dummy_config.yml +31 -0
  10. data/spec/lib/fusuma_spec.rb +103 -0
  11. data/spec/lib/libinput-list-devices_iberianpig-XPS-9360.txt +181 -0
  12. data/spec/lib/libinput-list-devices_magic_trackpad.txt +51 -0
  13. data/spec/lib/libinput-list-devices_razer_razer_blade.txt +252 -0
  14. data/spec/lib/libinput-list-devices_thejinx0r.txt +361 -0
  15. data/spec/lib/libinput-list-devices_unavailable.txt +36 -0
  16. data/spec/lib/libinput_command_spec.rb +167 -0
  17. data/spec/lib/plugin/base_spec.rb +74 -0
  18. data/spec/lib/plugin/buffers/buffer_spec.rb +80 -0
  19. data/spec/lib/plugin/buffers/dummy_buffer.rb +20 -0
  20. data/spec/lib/plugin/buffers/gesture_buffer_spec.rb +172 -0
  21. data/spec/lib/plugin/detectors/detector_spec.rb +43 -0
  22. data/spec/lib/plugin/detectors/dummy_detector.rb +24 -0
  23. data/spec/lib/plugin/detectors/pinch_detector_spec.rb +119 -0
  24. data/spec/lib/plugin/detectors/rotate_detector_spec.rb +125 -0
  25. data/spec/lib/plugin/detectors/swipe_detector_spec.rb +118 -0
  26. data/spec/lib/plugin/events/event_spec.rb +30 -0
  27. data/spec/lib/plugin/events/records/gesture_record_spec.rb +22 -0
  28. data/spec/lib/plugin/events/records/record_spec.rb +31 -0
  29. data/spec/lib/plugin/events/records/text_record_spec.rb +26 -0
  30. data/spec/lib/plugin/executors/command_executor_spec.rb +57 -0
  31. data/spec/lib/plugin/executors/executor_spec.rb +160 -0
  32. data/spec/lib/plugin/filters/filter_spec.rb +92 -0
  33. data/spec/lib/plugin/filters/libinput_filter_spec.rb +120 -0
  34. data/spec/lib/plugin/inputs/input_spec.rb +70 -0
  35. data/spec/lib/plugin/inputs/libinput_command_input_spec.rb +120 -0
  36. data/spec/lib/plugin/inputs/timer_input_spec.rb +40 -0
  37. data/spec/lib/plugin/manager_spec.rb +27 -0
  38. data/spec/lib/plugin/parsers/parser_spec.rb +45 -0
  39. data/spec/spec_helper.rb +20 -0
  40. metadata +74 -20
  41. data/.github/FUNDING.yml +0 -8
  42. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -32
  43. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -17
  44. data/.github/pull_request_template.md +0 -9
  45. data/.github/stale.yml +0 -18
  46. data/.gitignore +0 -17
  47. data/.reek.yml +0 -96
  48. data/.rspec +0 -2
  49. data/.rubocop.yml +0 -43
  50. data/.rubocop_todo.yml +0 -55
  51. data/.solargraph.yml +0 -16
  52. data/.travis.yml +0 -9
  53. data/CHANGELOG.md +0 -456
  54. data/CODE_OF_CONDUCT.md +0 -74
  55. data/CONTRIBUTING.md +0 -72
  56. data/Gemfile +0 -23
  57. data/Rakefile +0 -15
  58. data/fusuma.gemspec +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8b830de9940632862b66b2cd6dbd6cf9ead713a24d7913d31baae7baacef348
4
- data.tar.gz: e55c53522a2184c8e6197bc12c4ca203cd844f1277dafbfe02fde48ae8f0d8c6
3
+ metadata.gz: 0b18c602c00e13b108d71c64d02a04798614bb7b4296cc886127c21a128dafd2
4
+ data.tar.gz: b4d146e105abd99d5d4cc4f65dee9da5c9e9f1ad35b4c8ca8815ca64664d9a1c
5
5
  SHA512:
6
- metadata.gz: 8153cf247654a3b70f976f74b0c3d791a962185fec288286f625448e8c23c6b53e134acff8d2ebad51eebdd51fefe8539a8da11c5abbd7744b90f6f943b3316e
7
- data.tar.gz: 5065d471bfa721b9e973ac276ffb60db09ed1a5e4f967fa8dd7010856d6709b9c44ea3b9cd5fab82c2b2ae2467a0b072f14a3c779db331abbcda1b9fa479a276
6
+ metadata.gz: 4e5bd0ad216bfadd274e3f4a48f96941d27fd80bddf940804228b8a691d8c0180ab7ffd92a2733a3f0e72e5a1ca9ced8797404058cad169aa4a45c3b9ded149d
7
+ data.tar.gz: f7daa7ba96974bdfa6840d4cc081cf1de3883e10d44e65b7f7370966b7822fc86f39d2dcb1af3ab9b1f385a7c44455da98e4a7cf5811c98fef98f0e759a75e8b
@@ -27,9 +27,9 @@ module Fusuma
27
27
  gemspec_path = Dir.glob("#{match_data[1]}/#{match_data[2]}/*.gemspec").first
28
28
  raise "Not Found: #{match_data[1]}/#{match_data[2]}/*.gemspec" unless gemspec_path
29
29
 
30
- gemspec = Gem::Specification.load gemspec_path
31
- fusuma_gemspec = Gem::Specification.load File.expand_path('../../../fusuma.gemspec',
32
- __dir__)
30
+ gemspec = Gem::Specification.load(gemspec_path)
31
+ fusuma_gemspec_path = File.expand_path('../../../fusuma.gemspec', __dir__)
32
+ fusuma_gemspec = Gem::Specification.load(fusuma_gemspec_path)
33
33
  if gemspec.dependencies.find { |d| d.name == 'fusuma' }&.match?(fusuma_gemspec)
34
34
  require siblings_plugin
35
35
  else
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fusuma
4
- VERSION = '2.0.0'
4
+ VERSION = '2.0.1'
5
5
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tempfile'
4
+ require './lib/fusuma/config'
5
+
6
+ module Fusuma
7
+ module ConfigHelper
8
+ module_function
9
+
10
+ def load_config_yml=(string)
11
+ Config.custom_path = Tempfile.open do |temp_file|
12
+ temp_file.tap { |f| f.write(string) }
13
+ end
14
+ end
15
+
16
+ def clear_config_yml
17
+ Config.custom_path = nil
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,97 @@
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
+ let(:keymap) do
11
+ {
12
+ 'swipe' => {
13
+ 3 => {
14
+ 'left' => { 'command' => 'alt+Left' },
15
+ 'right' => { 'command' => 'alt+Right' }
16
+ },
17
+ 4 => {
18
+ 'left' => { 'command' => 'super+Left' },
19
+ 'right' => { 'command' => 'super+Right' }
20
+ }
21
+ },
22
+ 'pinch' => {
23
+ 'in' => { 'command' => 'ctrl+plus' },
24
+ 'out' => { 'command' => 'ctrl+minus' }
25
+ }
26
+ }
27
+ end
28
+
29
+ let(:keymap_without_finger) do
30
+ {
31
+ 'swipe' => {
32
+ 'left' => { 'command' => 'alt+Left' }
33
+ }
34
+ }
35
+ end
36
+
37
+ describe '.custom_path=' do
38
+ before { Singleton.__init__(Config) }
39
+ it 'should reload keymap file' do
40
+ keymap = Config.instance.keymap
41
+ Config.custom_path = './spec/lib/dummy_config.yml'
42
+ custom_keymap = Config.instance.keymap
43
+ expect(keymap).not_to eq custom_keymap
44
+ end
45
+ end
46
+
47
+ describe '.search' do
48
+ let(:index) { nil }
49
+ subject { Config::Searcher.new.search(index, location: keymap.deep_symbolize_keys) }
50
+ context 'index correct order' do
51
+ let(:index) { Config::Index.new %w[pinch in command] }
52
+ it { is_expected.to eq 'ctrl+plus' }
53
+ end
54
+
55
+ context 'index include skippable key' do
56
+ let(:index) do
57
+ Config::Index.new [
58
+ Config::Index::Key.new('pinch'),
59
+ Config::Index::Key.new(2, skippable: true),
60
+ Config::Index::Key.new('out'),
61
+ Config::Index::Key.new('command')
62
+ ]
63
+ end
64
+ it { expect(Config::Searcher.skip { subject }).to eq 'ctrl+minus' }
65
+ end
66
+
67
+ context 'index include 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 { expect(Config::Searcher.skip { subject }).to eq 'ctrl+plus' }
79
+ end
80
+
81
+ context 'index incorrect order' do
82
+ let(:index) { Config::Index.new %w[in pinch 2 command] }
83
+ it { is_expected.not_to eq 'ctrl+plus' }
84
+ end
85
+ end
86
+
87
+ describe 'private_method: :cache' do
88
+ it 'should cache command' do
89
+ key = %w[event_type finger direction command].join(',')
90
+ value = 'shourtcut string'
91
+ searcher = Config::Searcher.new
92
+ searcher.send(:cache, key) { value }
93
+ expect(searcher.send(:cache, key)).to eq value
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,112 @@
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
+ let(:keymap_without_finger) do
29
+ {
30
+ 'swipe' => {
31
+ 'left' => { 'command' => 'alt+Left' }
32
+ }
33
+ }
34
+ end
35
+
36
+ describe '.custom_path=' do
37
+ before { Singleton.__init__(Config) }
38
+ it 'should reload keymap file' do
39
+ keymap = Config.instance.keymap
40
+ Config.custom_path = './spec/lib/dummy_config.yml'
41
+ custom_keymap = Config.instance.keymap
42
+ expect(keymap).not_to eq custom_keymap
43
+ end
44
+ end
45
+
46
+ describe '#reload' do
47
+ before { Singleton.__init__(Config) }
48
+ it 'set Seacher' do
49
+ old = Config.instance.searcher
50
+ Config.instance.reload
51
+ expect(Config.instance.searcher).not_to eq(old)
52
+ end
53
+ end
54
+
55
+ describe '#validate' do
56
+ context 'with valid yaml' do
57
+ before do
58
+ string = <<~CONFIG
59
+ swipe:
60
+ 3:
61
+ left:
62
+ command: echo 'swipe left'
63
+
64
+ CONFIG
65
+ @file_path = Tempfile.open do |temp_file|
66
+ temp_file.tap { |f| f.write(string) }
67
+ end
68
+ end
69
+
70
+ it 'should return Hash' do
71
+ Config.instance.validate(@file_path)
72
+ end
73
+ end
74
+
75
+ context 'with invalid yaml' do
76
+ before do
77
+ string = <<~CONFIG
78
+ this is not yaml
79
+ CONFIG
80
+ @file_path = Tempfile.open do |temp_file|
81
+ temp_file.tap { |f| f.write(string) }
82
+ end
83
+ end
84
+
85
+ it 'raise InvalidFileError' do
86
+ expect { Config.instance.validate(@file_path) }.to raise_error(Config::InvalidFileError)
87
+ end
88
+
89
+ context 'with duplicated key' do
90
+ before do
91
+ string = <<~CONFIG
92
+ pinch:
93
+ 2:
94
+ in:
95
+ command: "xdotool keydown ctrl click 4 keyup ctrl" # threshold: 0.5, interval: 0.5
96
+ 2:
97
+ out:
98
+ command: "xdotool keydown ctrl click 5 keyup ctrl" # threshold: 0.5, interval: 0.5
99
+ CONFIG
100
+ @file_path = Tempfile.open do |temp_file|
101
+ temp_file.tap { |f| f.write(string) }
102
+ end
103
+ end
104
+
105
+ it 'raise InvalidFileError' do
106
+ expect { Config.instance.validate(@file_path) }.to raise_error(Config::InvalidFileError)
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,28 @@
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
+ allow(Process).to receive(:fork)
19
+ end
20
+ it 'call Process.fork and Process.setproctitle' do
21
+ expect(Process).to receive(:fork).and_yield do
22
+ expect(Process).to receive(:setproctitle)
23
+ end
24
+ ForkTest.new.call
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,98 @@
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(Process).to receive(:waitpid).and_return(nil)
28
+
29
+ allow(POSIX::Spawn).to receive(:popen4)
30
+ .with(libinput_device_command)
31
+ .and_return([nil, @dummy_io, list_devices_output, @dummy_io])
32
+ end
33
+
34
+ context 'with XPS-9360 (have a correct device)' do
35
+ let(:list_devices_output) do
36
+ File.open('./spec/lib/libinput-list-devices_iberianpig-XPS-9360.txt')
37
+ end
38
+
39
+ it { expect(Device.available).to be_a Array }
40
+ it { expect(Device.available.map(&:name)).not_to include 'Power Button' }
41
+ it { expect(Device.available.map(&:name)).to include 'DLL075B:01 06CB:76AF Touchpad' }
42
+ end
43
+
44
+ context 'with no tap to click device (like a bluetooth apple trackpad)' do
45
+ let(:list_devices_output) do
46
+ File.open('spec/lib/libinput-list-devices_magic_trackpad.txt')
47
+ end
48
+
49
+ it { expect(Device.available).to be_a Array }
50
+ it { expect(Device.available.map(&:name)).to eq ['Christopher’s Trackpad', 'bcm5974'] }
51
+ end
52
+
53
+ context "context with the device's name not found at first line" do
54
+ let(:list_devices_output) do
55
+ File.open('spec/lib/libinput-list-devices_thejinx0r.txt')
56
+ end
57
+
58
+ it { expect(Device.available).to be_a Array }
59
+ it { expect(Device.available.map(&:name)).to include 'HTX USB HID Device HTX HID Device Touchpad' }
60
+ end
61
+
62
+ context 'when no devices' do
63
+ let(:list_devices_output) do
64
+ File.open('spec/lib/libinput-list-devices_unavailable.txt')
65
+ end
66
+
67
+ it 'should failed with exit' do
68
+ expect { Device.available }.to raise_error(SystemExit)
69
+ end
70
+
71
+ it 'should failed with printing error log' do
72
+ expect(MultiLogger).to receive(:error)
73
+ expect { Device.available }.to raise_error(SystemExit)
74
+ end
75
+ end
76
+
77
+ context 'with some device has same names' do
78
+ let(:list_devices_output) do
79
+ File.open('spec/lib/libinput-list-devices_razer_razer_blade.txt')
80
+ end
81
+
82
+ it { expect(Device.available).to be_a Array }
83
+ it 'should have capabilities' do
84
+ razer_devices = Device.all.group_by(&:name)['Razer Razer Blade']
85
+ expect(razer_devices.size).to eq 3
86
+ end
87
+
88
+ it 'should know capabilities' do
89
+ razer_devices = Device.all.group_by(&:name)['Razer Razer Blade']
90
+ capabilities = razer_devices.map(&:capabilities)
91
+ expect(capabilities).to eq ['keyboard', 'keyboard pointer', 'pointer']
92
+ keyboard_devices = razer_devices.select { |d| d.capabilities == 'keyboard' }
93
+ expect(keyboard_devices.size).to eq 1
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,31 @@
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'
@@ -0,0 +1,103 @@
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