fusuma 2.0.0 → 2.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.
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