fusuma 2.0.0.pre → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +50 -11
  3. data/fusuma.gemspec +5 -6
  4. data/lib/fusuma.rb +87 -33
  5. data/lib/fusuma/config.rb +33 -40
  6. data/lib/fusuma/config/index.rb +34 -8
  7. data/lib/fusuma/config/searcher.rb +80 -4
  8. data/lib/fusuma/custom_process.rb +13 -0
  9. data/lib/fusuma/device.rb +19 -6
  10. data/lib/fusuma/environment.rb +4 -3
  11. data/lib/fusuma/hash_support.rb +40 -0
  12. data/lib/fusuma/libinput_command.rb +10 -15
  13. data/lib/fusuma/multi_logger.rb +2 -6
  14. data/lib/fusuma/plugin/base.rb +18 -15
  15. data/lib/fusuma/plugin/buffers/buffer.rb +3 -2
  16. data/lib/fusuma/plugin/buffers/gesture_buffer.rb +34 -25
  17. data/lib/fusuma/plugin/buffers/timer_buffer.rb +3 -3
  18. data/lib/fusuma/plugin/detectors/detector.rb +26 -5
  19. data/lib/fusuma/plugin/detectors/pinch_detector.rb +109 -58
  20. data/lib/fusuma/plugin/detectors/rotate_detector.rb +91 -50
  21. data/lib/fusuma/plugin/detectors/swipe_detector.rb +93 -56
  22. data/lib/fusuma/plugin/events/event.rb +5 -4
  23. data/lib/fusuma/plugin/events/records/context_record.rb +27 -0
  24. data/lib/fusuma/plugin/events/records/gesture_record.rb +9 -6
  25. data/lib/fusuma/plugin/events/records/index_record.rb +46 -14
  26. data/lib/fusuma/plugin/events/records/record.rb +1 -1
  27. data/lib/fusuma/plugin/events/records/text_record.rb +2 -1
  28. data/lib/fusuma/plugin/executors/command_executor.rb +21 -4
  29. data/lib/fusuma/plugin/executors/executor.rb +45 -3
  30. data/lib/fusuma/plugin/filters/filter.rb +1 -1
  31. data/lib/fusuma/plugin/filters/libinput_device_filter.rb +6 -7
  32. data/lib/fusuma/plugin/filters/libinput_timeout_filter.rb +2 -2
  33. data/lib/fusuma/plugin/inputs/input.rb +20 -7
  34. data/lib/fusuma/plugin/inputs/libinput_command_input.rb +17 -5
  35. data/lib/fusuma/plugin/inputs/timer_input.rb +7 -7
  36. data/lib/fusuma/plugin/manager.rb +22 -29
  37. data/lib/fusuma/plugin/parsers/libinput_gesture_parser.rb +10 -8
  38. data/lib/fusuma/plugin/parsers/parser.rb +8 -9
  39. data/lib/fusuma/string_support.rb +16 -0
  40. data/lib/fusuma/version.rb +1 -1
  41. data/spec/helpers/config_helper.rb +20 -0
  42. data/spec/lib/config/searcher_spec.rb +97 -0
  43. data/spec/lib/config_spec.rb +112 -0
  44. data/spec/lib/custom_process_spec.rb +28 -0
  45. data/spec/lib/device_spec.rb +96 -0
  46. data/spec/lib/dummy_config.yml +31 -0
  47. data/spec/lib/fusuma_spec.rb +103 -0
  48. data/spec/lib/libinput-list-devices_iberianpig-XPS-9360.txt +181 -0
  49. data/spec/lib/libinput-list-devices_magic_trackpad.txt +51 -0
  50. data/spec/lib/libinput-list-devices_razer_razer_blade.txt +252 -0
  51. data/spec/lib/libinput-list-devices_thejinx0r.txt +361 -0
  52. data/spec/lib/libinput-list-devices_unavailable.txt +36 -0
  53. data/spec/lib/libinput_command_spec.rb +160 -0
  54. data/spec/lib/plugin/base_spec.rb +74 -0
  55. data/spec/lib/plugin/buffers/buffer_spec.rb +80 -0
  56. data/spec/lib/plugin/buffers/dummy_buffer.rb +20 -0
  57. data/spec/lib/plugin/buffers/gesture_buffer_spec.rb +172 -0
  58. data/spec/lib/plugin/detectors/detector_spec.rb +43 -0
  59. data/spec/lib/plugin/detectors/dummy_detector.rb +24 -0
  60. data/spec/lib/plugin/detectors/pinch_detector_spec.rb +119 -0
  61. data/spec/lib/plugin/detectors/rotate_detector_spec.rb +125 -0
  62. data/spec/lib/plugin/detectors/swipe_detector_spec.rb +118 -0
  63. data/spec/lib/plugin/events/event_spec.rb +30 -0
  64. data/spec/lib/plugin/events/records/gesture_record_spec.rb +22 -0
  65. data/spec/lib/plugin/events/records/record_spec.rb +31 -0
  66. data/spec/lib/plugin/events/records/text_record_spec.rb +26 -0
  67. data/spec/lib/plugin/executors/command_executor_spec.rb +57 -0
  68. data/spec/lib/plugin/executors/executor_spec.rb +160 -0
  69. data/spec/lib/plugin/filters/filter_spec.rb +92 -0
  70. data/spec/lib/plugin/filters/libinput_filter_spec.rb +120 -0
  71. data/spec/lib/plugin/inputs/input_spec.rb +70 -0
  72. data/spec/lib/plugin/inputs/libinput_command_input_spec.rb +121 -0
  73. data/spec/lib/plugin/inputs/timer_input_spec.rb +40 -0
  74. data/spec/lib/plugin/manager_spec.rb +27 -0
  75. data/spec/lib/plugin/parsers/parser_spec.rb +45 -0
  76. data/spec/spec_helper.rb +20 -0
  77. metadata +84 -38
  78. data/.github/FUNDING.yml +0 -8
  79. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -32
  80. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -17
  81. data/.github/pull_request_template.md +0 -9
  82. data/.github/stale.yml +0 -18
  83. data/.gitignore +0 -17
  84. data/.reek.yml +0 -96
  85. data/.rspec +0 -2
  86. data/.rubocop.yml +0 -40
  87. data/.rubocop_todo.yml +0 -40
  88. data/.travis.yml +0 -11
  89. data/CHANGELOG.md +0 -456
  90. data/CODE_OF_CONDUCT.md +0 -74
  91. data/CONTRIBUTING.md +0 -72
  92. data/Gemfile +0 -18
  93. data/Rakefile +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd6d9f73a5476aed954644b4d5f7caa9627779139bc84e301fa2ae67fbb1d71f
4
- data.tar.gz: e893683da4aa5f235481ec32bf45a6a2386bc6b64989f36617b6806c538602b3
3
+ metadata.gz: 5d8b83e60047931022dab6daf54c40da12ec392b638d44c21491528ec7e13bed
4
+ data.tar.gz: 6e491edb08ad8b2c7f277986cf7d9226663867c1013fec52b04740649e35770d
5
5
  SHA512:
6
- metadata.gz: 55b7d3393e283bc459b865d293839d6aa2286db4ece74b14d9b50c05726f4d5bfb32609b79541ad816b0ebdebb687b948f03f53fdd1e4d070bf470af56360c84
7
- data.tar.gz: f9d5b36287ccd132687497f8f527fc1ef90b0dc818feccf2f9cc6db0b76371a30832467df2d8aa0fca8ee3c5804551da8470b34784c185da73dc08ae507034de
6
+ metadata.gz: 015112ebf7229f9d48c00735007a598d727bda17e16f4da3b4a6b1d3c8f05ce106d709aabe300414c1232cebc1f52e834fb6cca1961507a60ce6f7528058513a
7
+ data.tar.gz: c489bd3dbf6c6dd1227e3864abe9c075f6288cf448b8a2b7e85ef092c0586e75b24c76dda16e370ee92bc749fbe378e73bfa376d732dca474cfa43e580af6bfe
data/README.md CHANGED
@@ -17,7 +17,7 @@ This gem makes your linux able to recognize swipes or pinchs and assign commands
17
17
 
18
18
  ## Installation
19
19
 
20
- ### 1. Grant permission to read the touchpad device
20
+ ### Grant permission to read the touchpad device
21
21
 
22
22
  **IMPORTANT**: You **MUST** be a member of the **INPUT** group to read touchpad by Fusuma.
23
23
 
@@ -31,7 +31,9 @@ Then, You apply the change with no logout or reboot.
31
31
  $ newgrp input
32
32
  ```
33
33
 
34
- ### 2. Install libinput-tools
34
+ ### For Debian Based Distros (Ubuntu, Debian, Mint, Pop!OS)
35
+
36
+ #### 1. Install libinput-tools
35
37
 
36
38
  You need `libinput` release 1.0 or later.
37
39
 
@@ -39,7 +41,7 @@ You need `libinput` release 1.0 or later.
39
41
  $ sudo apt-get install libinput-tools
40
42
  ```
41
43
 
42
- ### 3. Install Ruby
44
+ #### 2. Install Ruby
43
45
 
44
46
  Fusuma runs in Ruby, so you must install it first.
45
47
 
@@ -47,13 +49,13 @@ Fusuma runs in Ruby, so you must install it first.
47
49
  $ sudo apt-get install ruby
48
50
  ```
49
51
 
50
- ### 4. Install Fusuma
52
+ #### 3. Install Fusuma
51
53
 
52
54
  ```bash
53
55
  $ sudo gem install fusuma
54
56
  ```
55
57
 
56
- ### 5. Install xdotool (optional)
58
+ #### 4. Install xdotool (optional)
57
59
 
58
60
  For sending shortcuts:
59
61
 
@@ -61,6 +63,42 @@ For sending shortcuts:
61
63
  $ sudo apt-get install xdotool
62
64
  ```
63
65
 
66
+ ### For Arch Based Distros (Manjaro, Arch)
67
+
68
+ #### 1. Install libinput.
69
+
70
+ You need `libinput` release 1.0 or later. This is most probably installed by default on Manjaro
71
+
72
+ ```z-h
73
+ $ sudo pacman -S libinput
74
+ ```
75
+
76
+ #### 2. Install Ruby
77
+
78
+ Fusuma runs in Ruby, so you must install it first.
79
+
80
+ ```zsh
81
+ $ sudo pacman -S ruby
82
+ ```
83
+
84
+ #### 3. Install Fusuma
85
+
86
+ **Note:** By default in Arch Linux, when running ```gem```, gems are installed per-user (into ```~/.gem/ruby/```), instead of system-wide (into ```/usr/lib/ruby/gems/```). This is considered the best way to manage gems on Arch, because otherwise they might interfere with gems installed by Pacman. (From Arch Wiki)
87
+
88
+ To install gems system-wide, see any of the methods listed on [Arch Wiki](https://wiki.archlinux.org/index.php/ruby#Installing_gems_system-wide)
89
+
90
+ ```zsh
91
+ $ sudo gem install fusuma
92
+ ```
93
+
94
+ #### 4. Install xdotool (optional)
95
+
96
+ For sending shortcuts:
97
+
98
+ ```zsh
99
+ $ sudo pacman -S xdotool
100
+ ```
101
+
64
102
  ### Touchpad not working in GNOME
65
103
 
66
104
  Ensure the touchpad events are being sent to the GNOME desktop by running the following command:
@@ -292,12 +330,13 @@ Fusuma plugins are provided with the `fusuma-plugin-XXXXX` naming convention and
292
330
 
293
331
  ### Available plugins
294
332
 
295
- | Name | About |
296
- | ------------------------------------------------------------------------------ | --------------------------------------------- |
297
- | [fusuma-plugin-sendkey](https://github.com/iberianpig/fusuma-plugin-sendkey) | Emulates keyboard events |
298
- | [fusuma-plugin-wmctrl](https://github.com/iberianpig/fusuma-plugin-wmctrl) | Manages Window and Workspace |
299
- | [fusuma-plugin-keypress](https://github.com/iberianpig/fusuma-plugin-keypress) | Detects gestures while pressing multiple keys |
300
- | [fusuma-plugin-tap](https://github.com/iberianpig/fusuma-plugin-tap) | Detects Tap and Hold gestures |
333
+ | Name | Version | About |
334
+ | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------- |
335
+ | [fusuma-plugin-sendkey](https://github.com/iberianpig/fusuma-plugin-sendkey) | ![Gem Version](https://badge.fury.io/rb/fusuma-plugin-sendkey.svg) | Emulates keyboard events |
336
+ | [fusuma-plugin-wmctrl](https://github.com/iberianpig/fusuma-plugin-wmctrl) | ![Gem Version](https://badge.fury.io/rb/fusuma-plugin-wmctrl.svg) | Manages Window and Workspace |
337
+ | [fusuma-plugin-keypress](https://github.com/iberianpig/fusuma-plugin-keypress) | ![Gem Version](https://badge.fury.io/rb/fusuma-plugin-keypress.svg) | Detects gestures while pressing multiple keys |
338
+ | [fusuma-plugin-tap](https://github.com/iberianpig/fusuma-plugin-tap) | ![Gem Version](https://badge.fury.io/rb/fusuma-plugin-tap.svg) | Detects Tap and Hold gestures |
339
+ | [fusuma-plugin-appmatcher](https://github.com/iberianpig/fusuma-plugin-appmatcher) | ![Gem Version](https://badge.fury.io/rb/fusuma-plugin-appmatcher.svg) | Configure app-specific gestures |
301
340
 
302
341
  ## Tutorial Video
303
342
 
data/fusuma.gemspec CHANGED
@@ -10,19 +10,18 @@ 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 dirver on X11, Linux'
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 = `git ls-files -z`.split("\x0").reject do |f|
19
- f.match(%r{^(test|spec|features)/})
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']
24
23
  spec.metadata['yard.run'] = 'yri' # use "yard" to build full HTML docs.
25
24
 
26
- spec.required_ruby_version = '>= 2.3' # https://packages.ubuntu.com/search?keywords=ruby&searchon=names&exact=1&suite=all&section=main
27
- spec.add_dependency 'posix-spawn'
25
+ spec.required_ruby_version = '>= 2.5.1' # https://packages.ubuntu.com/search?keywords=ruby&searchon=names&exact=1&suite=all&section=main
26
+ # support bionic (18.04LTS) 2.5.1
28
27
  end
data/lib/fusuma.rb CHANGED
@@ -2,10 +2,10 @@
2
2
 
3
3
  require_relative './fusuma/version'
4
4
  require_relative './fusuma/multi_logger'
5
- require_relative './fusuma/config.rb'
6
- require_relative './fusuma/environment.rb'
7
- require_relative './fusuma/device.rb'
8
- require_relative './fusuma/plugin/manager.rb'
5
+ require_relative './fusuma/config'
6
+ require_relative './fusuma/environment'
7
+ require_relative './fusuma/device'
8
+ require_relative './fusuma/plugin/manager'
9
9
 
10
10
  # this is top level module
11
11
  module Fusuma
@@ -16,6 +16,8 @@ module Fusuma
16
16
  set_trap
17
17
  read_options(option)
18
18
  instance = new
19
+ ## NOTE: Uncomment following line to measure performance
20
+ # instance.run_with_lineprof
19
21
  instance.run
20
22
  end
21
23
 
@@ -62,68 +64,120 @@ module Fusuma
62
64
  end
63
65
 
64
66
  def run
65
- loop do
66
- event = input
67
- event || next
68
- clear_expired_events
69
- filtered = filter(event) || next
70
- parsed = parse(filtered) || next
71
- buffered = buffer(parsed) || next
72
- detected = detect(buffered) || next
73
- merged = merge(detected) || next
74
- execute(merged)
67
+ loop { pipeline }
68
+ end
69
+
70
+ def pipeline
71
+ event = input || return
72
+ clear_expired_events
73
+ filtered = filter(event) || return
74
+ parsed = parse(filtered) || return
75
+ buffered = buffer(parsed) || return
76
+ detected = detect(buffered) || return
77
+ condition, context, event = merge(detected) || return
78
+ execute(condition, context, event)
79
+ end
80
+
81
+ # For performance monitoring
82
+ def run_with_lineprof(count: 1000)
83
+ require 'rblineprof'
84
+ require 'rblineprof-report'
85
+
86
+ profile = lineprof(%r{#{Pathname.new(__FILE__).parent}/.}) do
87
+ count.times { pipeline }
75
88
  end
89
+ LineProf.report(profile)
90
+ exit 0
76
91
  end
77
92
 
93
+ # @return [Plugin::Events::Event]
78
94
  def input
79
95
  Plugin::Inputs::Input.select(@inputs)
80
96
  end
81
97
 
98
+ # @param [Plugin::Events::Event]
99
+ # @return [Plugin::Events::Event]
82
100
  def filter(event)
83
101
  event if @filters.any? { |f| f.filter(event) }
84
102
  end
85
103
 
104
+ # @param [Plugin::Events::Event]
105
+ # @return [Plugin::Events::Event]
86
106
  def parse(event)
87
107
  @parsers.reduce(event) { |e, p| p.parse(e) if e }
88
108
  end
89
109
 
110
+ # @param [Plugin::Events::Event]
111
+ # @return [Array<Plugin::Buffers::Buffer>]
112
+ # @return [NilClass]
90
113
  def buffer(event)
91
- @buffers.any? { |b| b.buffer(event) } && @buffers
114
+ @buffers.select { |b| b.buffer(event) }
92
115
  end
93
116
 
94
117
  # @param buffers [Array<Buffer>]
95
118
  # @return [Array<Event>]
96
119
  def detect(buffers)
97
- @detectors.each_with_object([]) do |detector, detected|
98
- if (event = detector.detect(buffers))
99
- detected << event
100
- end
120
+ matched_detectors = @detectors.select do |detector|
121
+ detector.watch? ||
122
+ buffers.any? { |b| detector.sources.include?(b.type) }
123
+ end
124
+
125
+ events = matched_detectors.each_with_object([]) do |detector, detected|
126
+ Array(detector.detect(@buffers)).each { |e| detected << e }
101
127
  end
128
+
129
+ return if events.empty?
130
+
131
+ events
102
132
  end
103
133
 
104
- # @param events [Array<Event>]
105
- # @return [Event] a Event merged all records from arguments
134
+ # @param events [Array<Plugin::Events::Event>]
135
+ # @return [Plugin::Events::Event] Event merged all records from arguments
106
136
  # @return [NilClass] when event is NOT given
107
137
  def merge(events)
108
- main_events, modifiers = events.partition { |event| event.record.mergable? }
109
- return nil unless (main_event = main_events.first)
138
+ index_events, context_events = events.partition { |event| event.record.type == :index }
139
+ main_events, modifiers = index_events.partition { |event| event.record.mergable? }
140
+ request_context = context_events.each_with_object({}) do |e, results|
141
+ results[e.record.name] = e.record.value
142
+ end
143
+ main_events.sort_by! { |e| e.record.trigger_priority }
144
+
145
+ condition = nil
146
+ matched_context = nil
147
+ event = main_events.find do |main_event|
148
+ matched_context = Config::Searcher.find_context(request_context) do
149
+ condition, index_record = Config::Searcher.find_condition do
150
+ main_event.record.merge(records: modifiers.map(&:record))
151
+ end
152
+ main_event if index_record
153
+ end
154
+ end
155
+ return if event.nil?
110
156
 
111
- main_event.record.merge(records: modifiers.map(&:record))
112
- main_event
157
+ [condition, matched_context, event]
113
158
  end
114
159
 
115
- def execute(event)
160
+ # @param event [Plugin::Events::Event]
161
+ def execute(condition, context, event)
116
162
  return unless event
117
163
 
118
- l = lambda do
119
- executor = @executors.find { |e| e.executable?(event) }
120
- executor&.execute(event)
164
+ # Find executable condition and executor
165
+ executor = Config::Searcher.with_context(context) do
166
+ Config::Searcher.with_condition(condition) do
167
+ @executors.find { |e| e.executable?(event) }
168
+ end
121
169
  end
122
170
 
123
- l.call ||
124
- Config::Searcher.skip { l.call } ||
125
- Config::Searcher.fallback { l.call } ||
126
- Config::Searcher.skip { Config::Searcher.fallback { l.call } }
171
+ return if executor.nil?
172
+
173
+ # Check interval and execute
174
+ Config::Searcher.with_context(context) do
175
+ Config::Searcher.with_condition(condition) do
176
+ executor.enough_interval?(event) &&
177
+ executor.update_interval(event) &&
178
+ executor.execute(event)
179
+ end
180
+ end
127
181
  end
128
182
 
129
183
  def clear_expired_events
data/lib/fusuma/config.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative './multi_logger.rb'
4
- require_relative './config/index.rb'
5
- require_relative './config/searcher.rb'
6
- require_relative './config/yaml_duplication_checker.rb'
3
+ require_relative './multi_logger'
4
+ require_relative './config/index'
5
+ require_relative './config/searcher'
6
+ require_relative './config/yaml_duplication_checker'
7
+ require_relative './hash_support'
7
8
  require 'singleton'
8
9
  require 'yaml'
9
10
 
@@ -12,13 +13,18 @@ module Fusuma
12
13
  # read keymap from yaml file
13
14
  class Config
14
15
  class NotFoundError < StandardError; end
16
+
15
17
  class InvalidFileError < StandardError; end
16
18
 
17
19
  include Singleton
18
20
 
19
21
  class << self
20
- def search(keys)
21
- instance.search(keys)
22
+ def search(index)
23
+ instance.search(index)
24
+ end
25
+
26
+ def find_execute_key(index)
27
+ instance.find_execute_key(index)
22
28
  end
23
29
 
24
30
  def custom_path=(new_path)
@@ -26,9 +32,7 @@ module Fusuma
26
32
  end
27
33
  end
28
34
 
29
- attr_reader :keymap
30
- attr_reader :custom_path
31
- attr_reader :searcher
35
+ attr_reader :keymap, :custom_path, :searcher
32
36
 
33
37
  def initialize
34
38
  @searcher = Searcher.new
@@ -49,8 +53,8 @@ module Fusuma
49
53
  self
50
54
  end
51
55
 
52
- # @return [Hash]
53
- # @raise [InvalidError]
56
+ # @return [Hash] If check passes
57
+ # @raise [InvalidFileError] If check does not pass
54
58
  def validate(path)
55
59
  duplicates = []
56
60
  YAMLDuplicationChecker.check(File.read(path), path) do |ignored, duplicate|
@@ -59,20 +63,30 @@ module Fusuma
59
63
  end
60
64
  raise InvalidFileError, "Detect duplicate keys #{duplicates}" unless duplicates.empty?
61
65
 
62
- yaml = YAML.load_file(path)
63
-
64
- raise InvalidFileError, 'Invaid YAML file' unless yaml.is_a? Hash
65
-
66
- yaml.deep_symbolize_keys
66
+ yamls = YAML.load_stream(File.read(path)).compact
67
+ yamls.map(&:deep_symbolize_keys)
67
68
  rescue StandardError => e
68
69
  MultiLogger.error e.message
69
70
  raise InvalidFileError, e.message
70
71
  end
71
72
 
72
73
  # @param index [Index]
73
- # @param location [Hash]
74
- def search(index, location: keymap)
75
- @searcher.search_with_cache(index, location: location)
74
+ # @param context [Hash]
75
+ def search(index)
76
+ @searcher.search_with_cache(index, location: keymap)
77
+ end
78
+
79
+ # @param index [Config::Index]
80
+ # @return Symbol
81
+ def find_execute_key(index)
82
+ @execute_keys ||= Plugin::Executors::Executor.plugins.map do |executor|
83
+ executor.new.execute_keys
84
+ end.flatten
85
+
86
+ execute_params = search(index)
87
+ return if execute_params.nil?
88
+
89
+ @execute_keys.find { |k| execute_params.keys.include?(k) }
76
90
  end
77
91
 
78
92
  private
@@ -104,24 +118,3 @@ module Fusuma
104
118
  end
105
119
  end
106
120
  end
107
-
108
- # activesupport-4.1.1/lib/active_support/core_ext/hash/keys.rb
109
- class Hash
110
- def deep_symbolize_keys
111
- deep_transform_keys do |key|
112
- begin
113
- key.to_sym
114
- rescue StandardError
115
- key
116
- end
117
- end
118
- end
119
-
120
- def deep_transform_keys(&block)
121
- result = {}
122
- each do |key, value|
123
- result[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys(&block) : value
124
- end
125
- result
126
- end
127
- end
@@ -19,6 +19,11 @@ module Fusuma
19
19
  [Key.new(keys)]
20
20
  end
21
21
  end
22
+
23
+ def inspect
24
+ @keys.map(&:inspect)
25
+ end
26
+
22
27
  attr_reader :keys
23
28
 
24
29
  def cache_key
@@ -32,23 +37,44 @@ module Fusuma
32
37
  end
33
38
  end
34
39
 
40
+ # @return [Index]
41
+ def with_context
42
+ keys = @keys.map do |key|
43
+ next if Searcher.skip? && key.skippable
44
+
45
+ if Searcher.fallback? && key.fallback
46
+ key.fallback
47
+ else
48
+ key
49
+ end
50
+ end
51
+ self.class.new(keys.compact)
52
+ end
53
+
35
54
  # Keys in Index
36
55
  class Key
37
56
  def initialize(symbol_word, skippable: false, fallback: nil)
38
57
  @symbol = begin
39
- symbol_word.to_sym
40
- rescue StandardError
41
- symbol_word
42
- end
58
+ symbol_word.to_sym
59
+ rescue StandardError
60
+ symbol_word
61
+ end
43
62
 
44
63
  @skippable = skippable
45
64
 
46
65
  @fallback = begin
47
- fallback.to_sym
48
- rescue StandardError
49
- fallback
50
- end
66
+ fallback.to_sym
67
+ rescue StandardError
68
+ fallback
69
+ end
51
70
  end
71
+
72
+ def inspect
73
+ skip_marker = @skippable && Searcher.skip? ? '(skip)' : ''
74
+ fallback_marker = @fallback && Searcher.fallback? ? '(fallback)' : ''
75
+ "#{@symbol}#{skip_marker}#{fallback_marker}"
76
+ end
77
+
52
78
  attr_reader :symbol, :skippable, :fallback
53
79
  end
54
80
  end