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
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ require './lib/fusuma/plugin/detectors/rotate_detector'
6
+ require './lib/fusuma/plugin/buffers/gesture_buffer'
7
+ require './lib/fusuma/plugin/events/event'
8
+ require './lib/fusuma/config'
9
+
10
+ module Fusuma
11
+ module Plugin
12
+ module Detectors
13
+ RSpec.describe RotateDetector do
14
+ before do
15
+ @detector = RotateDetector.new
16
+ @buffer = Buffers::GestureBuffer.new
17
+ end
18
+
19
+ around do |example|
20
+ ConfigHelper.load_config_yml = <<~CONFIG
21
+ threshold:
22
+ rotate: 1
23
+ CONFIG
24
+
25
+ example.run
26
+
27
+ Config.custom_path = nil
28
+ end
29
+
30
+ describe '#detect' do
31
+ context 'with no rotate event in buffer' do
32
+ before do
33
+ @buffer.clear
34
+ end
35
+ it { expect(@detector.detect([@buffer])).to eq nil }
36
+ end
37
+
38
+ context 'with not enough rotate events in buffer' do
39
+ before do
40
+ deltas = [
41
+ Events::Records::GestureRecord::Delta.new(0, 0, 0, 0, 0, 0.4),
42
+ Events::Records::GestureRecord::Delta.new(0, 0, 0, 0, 0, 0.5)
43
+ ]
44
+ events = create_events(deltas: deltas)
45
+
46
+ events.each { |event| @buffer.buffer(event) }
47
+ end
48
+ it 'should have repeat record' do
49
+ expect(@detector.detect([@buffer]).record.trigger).to eq :repeat
50
+ end
51
+ end
52
+
53
+ context 'with enough rotate IN event' do
54
+ before do
55
+ deltas = [
56
+ Events::Records::GestureRecord::Delta.new(0, 0, 0, 0, 0, 0.5),
57
+ Events::Records::GestureRecord::Delta.new(0, 0, 0, 0, 0, 0.6),
58
+ Events::Records::GestureRecord::Delta.new(0, 0, 0, 0, 0, 0.6)
59
+ ]
60
+ events = create_events(deltas: deltas)
61
+
62
+ events.each { |event| @buffer.buffer(event) }
63
+ end
64
+ it { expect(@detector.detect([@buffer])).to all be_a Events::Event }
65
+ it {
66
+ expect(@detector.detect([@buffer]).map(&:record)).to all be_a Events::Records::IndexRecord
67
+ }
68
+ it {
69
+ expect(@detector.detect([@buffer]).map(&:record).map(&:index)).to all be_a Config::Index
70
+ }
71
+ it 'should detect 3 fingers rotate-clockwise (oneshot/repeat)' do
72
+ events = @detector.detect([@buffer])
73
+ expect(events[0].record.index.keys.map(&:symbol))
74
+ .to eq([:rotate, 3, :clockwise])
75
+ expect(events[1].record.index.keys.map(&:symbol))
76
+ .to eq([:rotate, 3, :clockwise, :update])
77
+ end
78
+ end
79
+
80
+ context 'with enough rotate OUT event' do
81
+ before do
82
+ deltas = [
83
+ Events::Records::GestureRecord::Delta.new(0, 0, 0, 0, 0, -0.5),
84
+ Events::Records::GestureRecord::Delta.new(0, 0, 0, 0, 0, -0.6),
85
+ Events::Records::GestureRecord::Delta.new(0, 0, 0, 0, 0, -0.6)
86
+ ]
87
+ events = create_events(deltas: deltas)
88
+
89
+ events.each { |event| @buffer.buffer(event) }
90
+ end
91
+ it 'should detect 3 fingers rotate-counterclockwise' do
92
+ events = @detector.detect([@buffer])
93
+ indexes = events.map { |e| e.record.index.keys.map(&:symbol) }
94
+ expect(indexes).to eq(
95
+ [
96
+ [:rotate, 3, :counterclockwise],
97
+ [:rotate, 3, :counterclockwise, :update]
98
+ ]
99
+ )
100
+ end
101
+ end
102
+ end
103
+
104
+ private
105
+
106
+ def create_events(deltas: [])
107
+ record_type = RotateDetector::GESTURE_RECORD_TYPE
108
+ deltas.map do |delta|
109
+ status = if deltas[0].equal? delta
110
+ 'begin'
111
+ else
112
+ 'update'
113
+ end
114
+
115
+ gesture_record = Events::Records::GestureRecord.new(status: status,
116
+ gesture: record_type,
117
+ finger: 3,
118
+ delta: delta)
119
+ Events::Event.new(tag: 'libinput_gesture_parser', record: gesture_record)
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ require './lib/fusuma/plugin/detectors/swipe_detector'
6
+ require './lib/fusuma/plugin/buffers/gesture_buffer'
7
+ require './lib/fusuma/plugin/events/records/gesture_record'
8
+ require './lib/fusuma/config'
9
+
10
+ module Fusuma
11
+ module Plugin
12
+ module Detectors
13
+ RSpec.describe SwipeDetector do
14
+ before do
15
+ @detector = SwipeDetector.new
16
+ @buffer = Buffers::GestureBuffer.new
17
+ end
18
+
19
+ around do |example|
20
+ ConfigHelper.load_config_yml = <<~CONFIG
21
+ threshold:
22
+ swipe: 1
23
+ CONFIG
24
+
25
+ example.run
26
+
27
+ Config.custom_path = nil
28
+ end
29
+
30
+ describe '#detect' do
31
+ context 'with no swipe event in buffer' do
32
+ before do
33
+ @buffer.clear
34
+ end
35
+ it { expect(@detector.detect([@buffer])).to eq nil }
36
+ end
37
+
38
+ context 'with not enough swipe events in buffer' do
39
+ before do
40
+ deltas = [
41
+ Events::Records::GestureRecord::Delta.new(0, 0, 0, 0, 0, 0), # begin
42
+ Events::Records::GestureRecord::Delta.new(20, 0, 0, 0, 0, 0) # update
43
+ ]
44
+ events = create_events(deltas: deltas)
45
+
46
+ events.each { |event| @buffer.buffer(event) }
47
+ end
48
+ it 'should have repeat record' do
49
+ event = @detector.detect([@buffer])
50
+ expect(event.record.trigger).to eq :repeat
51
+ end
52
+ end
53
+
54
+ context 'with enough swipe RIGHT event' do
55
+ before do
56
+ deltas = [
57
+ Events::Records::GestureRecord::Delta.new(0, 0, 0, 0, 0, 0), # begin
58
+ Events::Records::GestureRecord::Delta.new(0, 0, 0, 0, 0, 0), # update
59
+ Events::Records::GestureRecord::Delta.new(31, 0, 0, 0, 0, 0) # update
60
+ ]
61
+ events = create_events(deltas: deltas)
62
+
63
+ events.each { |event| @buffer.buffer(event) }
64
+ end
65
+ it { expect(@detector.detect([@buffer])).to all be_a Events::Event }
66
+ it { expect(@detector.detect([@buffer]).map(&:record)).to all be_a Events::Records::IndexRecord }
67
+ it { expect(@detector.detect([@buffer]).map(&:record).map(&:index)).to all be_a Config::Index }
68
+ it 'should detect 3 fingers swipe-right' do
69
+ events = @detector.detect([@buffer])
70
+ expect(events[0].record.index.keys.map(&:symbol))
71
+ .to eq([:swipe, 3, :right])
72
+ expect(events[1].record.index.keys.map(&:symbol))
73
+ .to eq([:swipe, 3, :right, :update])
74
+ end
75
+ end
76
+
77
+ context 'with enough swipe DOWN event' do
78
+ before do
79
+ deltas = [
80
+ Events::Records::GestureRecord::Delta.new(0, 0, 0, 0),
81
+ Events::Records::GestureRecord::Delta.new(0, 0, 0, 0),
82
+ Events::Records::GestureRecord::Delta.new(0, 31, 0, 0)
83
+ ]
84
+ events = create_events(deltas: deltas)
85
+
86
+ events.each { |event| @buffer.buffer(event) }
87
+ end
88
+ it 'should detect 3 fingers swipe-down' do
89
+ events = @detector.detect([@buffer])
90
+ expect(events[0].record.index.keys.map(&:symbol))
91
+ .to eq([:swipe, 3, :down])
92
+ expect(events[1].record.index.keys.map(&:symbol))
93
+ .to eq([:swipe, 3, :down, :update])
94
+ end
95
+ end
96
+ end
97
+
98
+ private
99
+
100
+ def create_events(deltas: [])
101
+ record_type = SwipeDetector::GESTURE_RECORD_TYPE
102
+ deltas.map do |delta|
103
+ status = if deltas[0].equal? delta
104
+ 'begin'
105
+ else
106
+ 'update'
107
+ end
108
+ gesture_record = Events::Records::GestureRecord.new(status: status,
109
+ gesture: record_type,
110
+ finger: 3,
111
+ delta: delta)
112
+ Events::Event.new(tag: 'libinput_gesture_parser', record: gesture_record)
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require './lib/fusuma/plugin/events/event'
5
+
6
+ module Fusuma
7
+ module Plugin
8
+ module Events
9
+ RSpec.describe Event do
10
+ let(:event) { Event.new(**args) }
11
+ let(:args) { { tag: 'text', record: 'dummy_text' } }
12
+
13
+ class DummyRecord < Records::Record
14
+ end
15
+
16
+ describe '#record' do
17
+ context 'with text' do
18
+ it { expect(event.record).to be_a Records::Record }
19
+ end
20
+
21
+ context 'with Record' do
22
+ let(:args) { { tag: 'dummy_record', record: DummyRecord.new } }
23
+
24
+ it { expect(event.record).to be_a Records::Record }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require './lib/fusuma/plugin/events/records/gesture_record'
5
+
6
+ module Fusuma
7
+ module Plugin
8
+ module Events
9
+ module Records
10
+ RSpec.describe GestureRecord do
11
+ let(:record) do
12
+ described_class.new(status: 'updating',
13
+ gesture: 'swipe',
14
+ finger: 3,
15
+ direction: direction)
16
+ end
17
+ let(:direction) { GestureRecord::Delta.new(0, 0, 1, 0) }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require './lib/fusuma/plugin/events/records/record'
5
+
6
+ module Fusuma
7
+ module Plugin
8
+ module Events
9
+ module Records
10
+ RSpec.describe Record do
11
+ class DummyRecord < Records::Record
12
+ def type
13
+ :dummy
14
+ end
15
+ end
16
+ let(:record) { described_class.new }
17
+
18
+ describe '#type' do
19
+ it { expect { record.type }.to raise_error(NotImplementedError) }
20
+
21
+ context 'override #type' do
22
+ let(:record) { DummyRecord.new }
23
+ it { expect { record.type }.not_to raise_error(NotImplementedError) }
24
+ it { expect(record.type).to eq :dummy }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require './lib/fusuma/plugin/events/records/text_record'
5
+
6
+ module Fusuma
7
+ module Plugin
8
+ module Events
9
+ module Records
10
+ RSpec.describe TextRecord do
11
+ let(:record) { described_class.new('this is dummy') }
12
+
13
+ describe '#type' do
14
+ subject { record.type }
15
+ it { is_expected.to eq :text }
16
+ end
17
+
18
+ describe '#to_s' do
19
+ subject { record.to_s }
20
+ it { is_expected.to eq 'this is dummy' }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require './lib/fusuma/plugin/executors/command_executor'
5
+ require './lib/fusuma/plugin/events/event'
6
+
7
+ module Fusuma
8
+ module Plugin
9
+ module Executors
10
+ RSpec.describe CommandExecutor do
11
+ before do
12
+ index = Config::Index.new([:dummy, 1, :direction])
13
+ record = Events::Records::IndexRecord.new(index: index)
14
+ @event = Events::Event.new(tag: 'dummy_detector', record: record)
15
+ @executor = CommandExecutor.new
16
+ end
17
+
18
+ around do |example|
19
+ ConfigHelper.load_config_yml = <<~CONFIG
20
+ dummy:
21
+ 1:
22
+ direction:
23
+ command: 'echo dummy'
24
+ interval: 1
25
+ CONFIG
26
+
27
+ example.run
28
+
29
+ Config.custom_path = nil
30
+ end
31
+
32
+ describe '#execute' do
33
+ it 'spawn' do
34
+ command = 'echo dummy'
35
+ env = {}
36
+ expect(POSIX::Spawn).to receive(:spawn).with(env, command)
37
+ expect(Process).to receive(:detach).with(anything)
38
+ @executor.execute(@event)
39
+ end
40
+ end
41
+
42
+ describe '#executable?' do
43
+ context 'detector is matched with config file' do
44
+ it { expect(@executor.executable?(@event)).to be_truthy }
45
+ end
46
+
47
+ context 'detector is NOT matched with config file' do
48
+ before do
49
+ @event.tag = 'invalid'
50
+ end
51
+ it { expect(@executor.executable?(@event)).to be_falsey }
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,160 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ require './lib/fusuma/config'
6
+ require './lib/fusuma/plugin/executors/executor'
7
+ require './lib/fusuma/plugin/detectors/detector'
8
+ require './lib/fusuma/plugin/events/event'
9
+
10
+ module Fusuma
11
+ module Plugin
12
+ module Executors
13
+ RSpec.describe Executor do
14
+ before { @executor = Executor.new }
15
+
16
+ describe '#execute' do
17
+ it do
18
+ expect { @executor.execute('dummy') }.to raise_error(NotImplementedError)
19
+ end
20
+ end
21
+
22
+ describe '#executable?' do
23
+ it do
24
+ expect { @executor.executable?('dummy') }.to raise_error(NotImplementedError)
25
+ end
26
+ end
27
+ end
28
+
29
+ class DummyExecutor < Executor
30
+ def execute(event)
31
+ index = Config::Index.new([*event.record.index.keys, :dummy])
32
+ content = Config.search(index)
33
+
34
+ # stdout
35
+ puts content if executable?(event)
36
+ end
37
+
38
+ def executable?(event)
39
+ event.tag == 'dummy'
40
+ end
41
+ end
42
+
43
+ RSpec.describe DummyExecutor do
44
+ before do
45
+ index = Config::Index.new([:dummy_gesture,
46
+ Config::Index::Key.new(:dummy_direction, skippable: true)])
47
+ record = Events::Records::IndexRecord.new(index: index)
48
+ @event = Events::Event.new(tag: 'dummy', record: record)
49
+ @executor = DummyExecutor.new
50
+ end
51
+
52
+ around do |example|
53
+ ConfigHelper.load_config_yml = <<~CONFIG
54
+ dummy_gesture:
55
+ dummy_direction:
56
+ dummy: 'echo dummy'
57
+ interval: 0.3
58
+
59
+ plugin:
60
+ executors:
61
+ dummy_executor:
62
+ dummy: dummy
63
+ CONFIG
64
+
65
+ example.run
66
+
67
+ Config.custom_path = nil
68
+ end
69
+
70
+ describe '#execute' do
71
+ it { expect { @executor.execute(@event) }.to output("echo dummy\n").to_stdout }
72
+ context 'without executable' do
73
+ before do
74
+ allow(@executor).to receive(:executable?).and_return false
75
+ end
76
+ it { expect { @executor.execute(@event) }.not_to output("echo dummy\n").to_stdout }
77
+ end
78
+ end
79
+
80
+ describe '#executable?' do
81
+ it { expect(@executor.executable?(@event)).to be_truthy }
82
+ end
83
+
84
+ describe 'interval' do
85
+ it 'should return interval from Config' do
86
+ interval_time = 0.3 * DummyExecutor::BASE_ONESHOT_INTERVAL
87
+ expect(@executor.interval(@event)).to eq interval_time
88
+ end
89
+
90
+ context 'without skippable direction' do
91
+ around do |example|
92
+ ConfigHelper.load_config_yml = <<~CONFIG
93
+ dummy_gesture:
94
+ interval: 0.1
95
+ dummy_direction:
96
+ dummy: 'echo dummy'
97
+
98
+ plugin:
99
+ executors:
100
+ dummy_executor:
101
+ dummy: dummy
102
+ CONFIG
103
+
104
+ example.run
105
+
106
+ Config.custom_path = nil
107
+ end
108
+ it 'should not return parent interval' do
109
+ expect(@executor.interval(@event)).to eq DummyExecutor::BASE_ONESHOT_INTERVAL
110
+ expect(@executor.interval(@event)).not_to eq 0.1 * DummyExecutor::BASE_ONESHOT_INTERVAL
111
+ end
112
+
113
+ context 'with Config::Searcher.skip' do
114
+ it 'should return parent interval' do
115
+ Config::Searcher.skip do
116
+ expect(@executor.interval(@event)).to eq 0.1 * DummyExecutor::BASE_ONESHOT_INTERVAL
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+
123
+ describe 'enough_interval?' do
124
+ it 'should return true at first time' do
125
+ expect(@executor.enough_interval?(@event)).to eq true
126
+ end
127
+
128
+ context 'after update_interval' do
129
+ before do
130
+ @executor.update_interval(@event)
131
+ end
132
+ it 'should return false' do
133
+ expect(@executor.enough_interval?(@event)).to eq false
134
+ end
135
+
136
+ context 'after wait interval time' do
137
+ before do
138
+ # dummy_gesture/dummy_direction/interval => 0.3
139
+ interval_time = 0.3 * DummyExecutor::BASE_ONESHOT_INTERVAL
140
+
141
+ @event2 = Events::Event.new(
142
+ time: @event.time + interval_time,
143
+ tag: 'dummy',
144
+ record: @event.record
145
+ )
146
+ end
147
+ it 'should return true after wait' do
148
+ expect(@executor.enough_interval?(@event2)).to eq true
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ describe '#config_params' do
155
+ it { expect(@executor.config_params).to eq(dummy: 'dummy') }
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end