fusuma 2.0.0.pre2 → 2.0.4
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.
- checksums.yaml +4 -4
- data/README.md +7 -6
- data/fusuma.gemspec +3 -5
- data/lib/fusuma/config/searcher.rb +2 -0
- data/lib/fusuma/device.rb +3 -3
- data/lib/fusuma/environment.rb +1 -0
- data/lib/fusuma/libinput_command.rb +12 -12
- data/lib/fusuma/plugin/executors/command_executor.rb +10 -10
- data/lib/fusuma/plugin/inputs/input.rb +1 -0
- data/lib/fusuma/plugin/inputs/libinput_command_input.rb +9 -2
- data/lib/fusuma/plugin/manager.rb +12 -1
- data/lib/fusuma/version.rb +1 -1
- data/spec/helpers/config_helper.rb +20 -0
- data/spec/lib/config/searcher_spec.rb +97 -0
- data/spec/lib/config_spec.rb +112 -0
- data/spec/lib/custom_process_spec.rb +28 -0
- data/spec/lib/device_spec.rb +96 -0
- data/spec/lib/dummy_config.yml +31 -0
- data/spec/lib/fusuma_spec.rb +103 -0
- data/spec/lib/libinput-list-devices_iberianpig-XPS-9360.txt +181 -0
- data/spec/lib/libinput-list-devices_magic_trackpad.txt +51 -0
- data/spec/lib/libinput-list-devices_razer_razer_blade.txt +252 -0
- data/spec/lib/libinput-list-devices_thejinx0r.txt +361 -0
- data/spec/lib/libinput-list-devices_unavailable.txt +36 -0
- data/spec/lib/libinput_command_spec.rb +164 -0
- data/spec/lib/plugin/base_spec.rb +74 -0
- data/spec/lib/plugin/buffers/buffer_spec.rb +80 -0
- data/spec/lib/plugin/buffers/dummy_buffer.rb +20 -0
- data/spec/lib/plugin/buffers/gesture_buffer_spec.rb +172 -0
- data/spec/lib/plugin/detectors/detector_spec.rb +43 -0
- data/spec/lib/plugin/detectors/dummy_detector.rb +24 -0
- data/spec/lib/plugin/detectors/pinch_detector_spec.rb +119 -0
- data/spec/lib/plugin/detectors/rotate_detector_spec.rb +125 -0
- data/spec/lib/plugin/detectors/swipe_detector_spec.rb +118 -0
- data/spec/lib/plugin/events/event_spec.rb +30 -0
- data/spec/lib/plugin/events/records/gesture_record_spec.rb +22 -0
- data/spec/lib/plugin/events/records/record_spec.rb +31 -0
- data/spec/lib/plugin/events/records/text_record_spec.rb +26 -0
- data/spec/lib/plugin/executors/command_executor_spec.rb +57 -0
- data/spec/lib/plugin/executors/executor_spec.rb +160 -0
- data/spec/lib/plugin/filters/filter_spec.rb +92 -0
- data/spec/lib/plugin/filters/libinput_filter_spec.rb +120 -0
- data/spec/lib/plugin/inputs/input_spec.rb +70 -0
- data/spec/lib/plugin/inputs/libinput_command_input_spec.rb +121 -0
- data/spec/lib/plugin/inputs/timer_input_spec.rb +40 -0
- data/spec/lib/plugin/manager_spec.rb +27 -0
- data/spec/lib/plugin/parsers/parser_spec.rb +45 -0
- data/spec/spec_helper.rb +20 -0
- metadata +83 -42
- data/.github/FUNDING.yml +0 -8
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -32
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -17
- data/.github/pull_request_template.md +0 -9
- data/.github/stale.yml +0 -18
- data/.gitignore +0 -17
- data/.reek.yml +0 -96
- data/.rspec +0 -2
- data/.rubocop.yml +0 -43
- data/.rubocop_todo.yml +0 -55
- data/.solargraph.yml +0 -16
- data/.travis.yml +0 -9
- data/CHANGELOG.md +0 -456
- data/CODE_OF_CONDUCT.md +0 -74
- data/CONTRIBUTING.md +0 -72
- data/Gemfile +0 -23
- data/Rakefile +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f19305771a0704b1f7294b9b54653f09d7d4f6153ffbdd19a6c23a753870b09
|
4
|
+
data.tar.gz: 3b6c9addcda816e7379e69bb258bd11f091ea39fbae37fc8e0ef4c9ca4b7dff7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 422dc7e58b8db650754c4939ec1946456bfdfb0a8e4af33d79a20d88d84190f393952e05e1d086f711fb1ee2e6c415c4ddf6861dba8d94bf84df4f4e0585374f
|
7
|
+
data.tar.gz: 02e75550adfd4a6f3e3d43b4a6326377d5182131bdd9d9f3ff3ca0abcb89888e0bca9eea8551868cc87edb0a706fb9b51ee97cc517e093566c7448729359ded2
|
data/README.md
CHANGED
@@ -330,12 +330,13 @@ Fusuma plugins are provided with the `fusuma-plugin-XXXXX` naming convention and
|
|
330
330
|
|
331
331
|
### Available plugins
|
332
332
|
|
333
|
-
| Name
|
334
|
-
|
|
335
|
-
| [fusuma-plugin-sendkey](https://github.com/iberianpig/fusuma-plugin-sendkey)
|
336
|
-
| [fusuma-plugin-wmctrl](https://github.com/iberianpig/fusuma-plugin-wmctrl) | Manages Window and Workspace |
|
337
|
-
| [fusuma-plugin-keypress](https://github.com/iberianpig/fusuma-plugin-keypress) | Detects gestures while pressing multiple keys |
|
338
|
-
| [fusuma-plugin-tap](https://github.com/iberianpig/fusuma-plugin-tap)
|
333
|
+
| Name | Version | About |
|
334
|
+
| ---------------------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------- |
|
335
|
+
| [fusuma-plugin-sendkey](https://github.com/iberianpig/fusuma-plugin-sendkey) |  | Emulates keyboard events |
|
336
|
+
| [fusuma-plugin-wmctrl](https://github.com/iberianpig/fusuma-plugin-wmctrl) |  | Manages Window and Workspace |
|
337
|
+
| [fusuma-plugin-keypress](https://github.com/iberianpig/fusuma-plugin-keypress) |  | Detects gestures while pressing multiple keys |
|
338
|
+
| [fusuma-plugin-tap](https://github.com/iberianpig/fusuma-plugin-tap) |  | Detects Tap and Hold gestures |
|
339
|
+
| [fusuma-plugin-appmatcher](https://github.com/iberianpig/fusuma-plugin-appmatcher) |  | Configure app-specific gestures |
|
339
340
|
|
340
341
|
## Tutorial Video
|
341
342
|
|
data/fusuma.gemspec
CHANGED
@@ -10,14 +10,13 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.authors = ['iberianpig']
|
11
11
|
spec.email = ['yhkyky@gmail.com']
|
12
12
|
|
13
|
-
spec.summary = 'Multitouch gestures with libinput driver
|
13
|
+
spec.summary = 'Multitouch gestures with libinput driver, Linux'
|
14
14
|
spec.description = 'Fusuma is multitouch gesture recognizer. This gem makes your touchpad on Linux able to recognize swipes or pinchs and assign command to them. Read installation on Github(https://github.com/iberianpig/fusuma#installation).'
|
15
15
|
spec.homepage = 'https://github.com/iberianpig/fusuma'
|
16
16
|
spec.license = 'MIT'
|
17
17
|
|
18
|
-
spec.files
|
19
|
-
|
20
|
-
end
|
18
|
+
spec.files = Dir['{bin,lib,exe}/**/*', 'LICENSE*', 'README*', '*.gemspec']
|
19
|
+
spec.test_files = Dir['{test,spec,features}/**/*']
|
21
20
|
spec.bindir = 'exe'
|
22
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
22
|
spec.require_paths = ['lib']
|
@@ -25,5 +24,4 @@ Gem::Specification.new do |spec|
|
|
25
24
|
|
26
25
|
spec.required_ruby_version = '>= 2.5.1' # https://packages.ubuntu.com/search?keywords=ruby&searchon=names&exact=1&suite=all§ion=main
|
27
26
|
# support bionic (18.04LTS) 2.5.1
|
28
|
-
spec.add_dependency 'posix-spawn'
|
29
27
|
end
|
data/lib/fusuma/device.rb
CHANGED
@@ -36,9 +36,9 @@ module Fusuma
|
|
36
36
|
# sort devices by capabilities of gesture
|
37
37
|
# @return [Array]
|
38
38
|
def all
|
39
|
-
@all ||= fetch_devices.
|
40
|
-
d.capabilities.match(/gesture/)
|
41
|
-
end
|
39
|
+
@all ||= fetch_devices.partition do |d|
|
40
|
+
d.capabilities.match?(/gesture/)
|
41
|
+
end.flatten
|
42
42
|
end
|
43
43
|
|
44
44
|
# @raise [SystemExit]
|
data/lib/fusuma/environment.rb
CHANGED
@@ -20,6 +20,7 @@ module Fusuma
|
|
20
20
|
libinput_command = Plugin::Inputs::LibinputCommandInput.new.command
|
21
21
|
MultiLogger.info "Fusuma: #{VERSION}"
|
22
22
|
MultiLogger.info "libinput: #{libinput_command.version}"
|
23
|
+
MultiLogger.info "ruby #{ RUBY_VERSION }p#{ RUBY_PATCHLEVEL }"
|
23
24
|
MultiLogger.info "OS: #{`uname -rsv`}".strip
|
24
25
|
MultiLogger.info "Distribution: #{`cat /etc/issue`}".strip
|
25
26
|
MultiLogger.info "Desktop session: #{`echo $DESKTOP_SESSION $XDG_SESSION_TYPE`}".strip
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'open3'
|
4
4
|
|
5
5
|
module Fusuma
|
6
6
|
# Execute libinput command
|
@@ -33,20 +33,20 @@ module Fusuma
|
|
33
33
|
def list_devices(&block)
|
34
34
|
cmd = list_devices_command
|
35
35
|
MultiLogger.debug(list_devices: cmd)
|
36
|
-
|
36
|
+
i, o, e, _w = Open3.popen3(cmd)
|
37
|
+
MultiLogger.error(e.read) if o.eof?
|
37
38
|
i.close
|
39
|
+
e.close
|
38
40
|
o.each(&block)
|
39
|
-
ensure
|
40
|
-
[i, o, e].each { |io| io.close unless io.closed? }
|
41
|
-
Process.waitpid(p)
|
42
41
|
end
|
43
42
|
|
44
|
-
# @return [Integer
|
45
|
-
def debug_events
|
46
|
-
@debug_events
|
47
|
-
|
48
|
-
|
49
|
-
|
43
|
+
# @return [Integer] return a latest line libinput debug-events
|
44
|
+
def debug_events(writer)
|
45
|
+
@debug_events ||= begin
|
46
|
+
pid = Process.spawn(debug_events_with_options, out: writer,
|
47
|
+
in: '/dev/null')
|
48
|
+
Process.detach(pid)
|
49
|
+
pid
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -60,7 +60,7 @@ module Fusuma
|
|
60
60
|
elsif which('libinput-list-devices')
|
61
61
|
'libinput-list-devices --version'
|
62
62
|
else
|
63
|
-
MultiLogger.error 'install libinput-tools'
|
63
|
+
MultiLogger.error 'Please install libinput-tools'
|
64
64
|
exit 1
|
65
65
|
end
|
66
66
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'posix/spawn'
|
4
3
|
require_relative './executor'
|
5
4
|
|
6
5
|
module Fusuma
|
@@ -15,18 +14,19 @@ module Fusuma
|
|
15
14
|
end
|
16
15
|
|
17
16
|
def execute(event)
|
18
|
-
search_command(event)
|
19
|
-
break unless command
|
17
|
+
command = search_command(event)
|
20
18
|
|
21
|
-
|
19
|
+
MultiLogger.info(command: command, args: event.record.args)
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
accel = args_accel(event)
|
22
|
+
additional_env = event.record.args
|
23
|
+
.deep_transform_keys(&:to_s)
|
24
|
+
.deep_transform_values { |v| (v * accel).to_s }
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
pid = Process.spawn(additional_env, command.to_s)
|
27
|
+
Process.detach(pid)
|
28
|
+
rescue SystemCallError => e
|
29
|
+
MultiLogger.error("#{event.record.index.keys}": e.message.to_s)
|
30
30
|
end
|
31
31
|
|
32
32
|
def executable?(event)
|
@@ -25,8 +25,9 @@ module Fusuma
|
|
25
25
|
# @return [IO]
|
26
26
|
def io
|
27
27
|
@io ||= begin
|
28
|
-
|
29
|
-
|
28
|
+
reader, writer = create_io
|
29
|
+
@pid = command.debug_events(writer)
|
30
|
+
reader
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
@@ -64,6 +65,12 @@ module Fusuma
|
|
64
65
|
def list_devices_command
|
65
66
|
config_params(:'libinput-list-devices')
|
66
67
|
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def create_io
|
72
|
+
IO.pipe
|
73
|
+
end
|
67
74
|
end
|
68
75
|
end
|
69
76
|
end
|
@@ -21,8 +21,19 @@ module Fusuma
|
|
21
21
|
def require_siblings_from_gems
|
22
22
|
search_key = File.join(plugin_dir_name, '*.rb')
|
23
23
|
Gem.find_latest_files(search_key).each do |siblings_plugin|
|
24
|
-
|
24
|
+
next unless siblings_plugin =~ %r{fusuma-plugin-(.+).*/lib/#{plugin_dir_name}/\1_.+.rb}
|
25
|
+
|
26
|
+
match_data = siblings_plugin.match(%r{(.*)/(.*)/lib/(.*)})
|
27
|
+
gemspec_path = Dir.glob("#{match_data[1]}/#{match_data[2]}/*.gemspec").first
|
28
|
+
raise "Not Found: #{match_data[1]}/#{match_data[2]}/*.gemspec" unless gemspec_path
|
29
|
+
|
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
|
+
if gemspec.dependencies.find { |d| d.name == 'fusuma' }&.match?(fusuma_gemspec)
|
25
34
|
require siblings_plugin
|
35
|
+
else
|
36
|
+
MultiLogger.warn "#{gemspec.name} #{gemspec.version} is incompatible with running #{fusuma_gemspec.name} #{fusuma_gemspec.version}"
|
26
37
|
end
|
27
38
|
end
|
28
39
|
end
|
data/lib/fusuma/version.rb
CHANGED
@@ -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
|