fusuma 2.5.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -15,37 +15,56 @@ module Fusuma
15
15
  fusuma_default_plugin_paths.each { |siblings_plugin| require(siblings_plugin) }
16
16
  end
17
17
 
18
- def fusuma_default_plugin_paths
19
- search_key = File.join("../../", plugin_dir_name, "*.rb")
20
- Dir.glob(File.expand_path("#{__dir__}/#{search_key}")).sort
21
- end
22
-
23
18
  def require_siblings_from_gems
24
19
  fusuma_external_plugin_paths.each { |siblings_plugin| require(siblings_plugin) }
25
20
  end
26
21
 
22
+ def exclude_path_pattern
23
+ %r{fusuma/plugin/[^/]*.rb}
24
+ end
25
+
26
+ def fusuma_default_plugin_paths
27
+ @_fusuma_default_plugin_paths ||= Dir.glob(File.expand_path("#{__dir__}/../../#{search_key}")).grep_v(exclude_path_pattern).sort
28
+ end
29
+
30
+ # @return [Array<String>] paths of external plugins (installed by gem)
27
31
  def fusuma_external_plugin_paths
28
- search_key = File.join(plugin_dir_name, "*.rb")
29
- Gem.find_latest_files(search_key).map do |siblings_plugin|
30
- next unless %r{fusuma-plugin-(.+).*/lib/#{plugin_dir_name}/.+\.rb}.match?(siblings_plugin)
31
-
32
- match_data = siblings_plugin.match(%r{(.*)/(.*)/lib/(.*)})
33
- gemspec_path = Dir.glob("#{match_data[1]}/#{match_data[2]}/*.gemspec").first
34
- raise "Not Found: #{match_data[1]}/#{match_data[2]}/*.gemspec" unless gemspec_path
35
-
36
- gemspec = Gem::Specification.load(gemspec_path)
37
- fusuma_gemspec_path = File.expand_path("../../../fusuma.gemspec", __dir__)
38
- fusuma_gemspec = Gem::Specification.load(fusuma_gemspec_path)
39
- if gemspec.dependencies.find { |d| d.name == "fusuma" }&.match?(fusuma_gemspec)
40
- siblings_plugin
41
- else
42
- MultiLogger.warn "#{gemspec.name} #{gemspec.version} is incompatible with running #{fusuma_gemspec.name} #{fusuma_gemspec.version}"
43
- end
44
- end.compact
32
+ @_fusuma_external_plugin_paths ||=
33
+ Gem.find_latest_files(search_key).map do |siblings_plugin|
34
+ next unless %r{fusuma-plugin-(.+).*/lib/#{plugin_dir_name}/.+\.rb}.match?(siblings_plugin)
35
+
36
+ match_data = siblings_plugin.match(%r{(.*)/(.*)/lib/(.*)})
37
+ plugin_gemspec_path = Dir.glob("#{match_data[1]}/#{match_data[2]}/*.gemspec").first
38
+ raise "Not Found: #{match_data[1]}/#{match_data[2]}/*.gemspec" unless plugin_gemspec_path
39
+
40
+ plugin_gemspec = Gem::Specification.load(plugin_gemspec_path)
41
+ fusuma_gemspec_path = File.expand_path("../../../fusuma.gemspec", __dir__)
42
+ fusuma_gemspec = Gem::Specification.load(fusuma_gemspec_path)
43
+
44
+ if plugin_gemspec.dependencies.find { |d| d.name == "fusuma" }&.match?(fusuma_gemspec)
45
+ siblings_plugin
46
+ else
47
+ MultiLogger.warn "#{plugin_gemspec.name} #{plugin_gemspec.version} is incompatible with running #{fusuma_gemspec.name} #{fusuma_gemspec.version}"
48
+ MultiLogger.warn "gemspec: #{plugin_gemspec_path}"
49
+ next
50
+ end
51
+ end.compact.grep_v(exclude_path_pattern).sort
52
+ end
53
+
54
+ # @return [String] search key for plugin
55
+ # @example
56
+ # search_key
57
+ # => "fusuma/plugin/detectors/*rb"
58
+ def search_key
59
+ File.join(plugin_dir_name, "*rb")
45
60
  end
46
61
 
47
62
  private
48
63
 
64
+ # @example
65
+ # plugin_dir_name
66
+ # => "fusuma/plugin/detectors"
67
+ # @return [String]
49
68
  def plugin_dir_name
50
69
  @plugin_class.name.match(/(Fusuma::.*)::/)[1].to_s.underscore
51
70
  end
@@ -70,6 +89,13 @@ module Fusuma
70
89
  load_paths << plugin_path
71
90
 
72
91
  manager = Manager.new(plugin_class)
92
+
93
+ @already_required ||= {}
94
+
95
+ key = manager.search_key
96
+ return if @already_required[key]
97
+
98
+ @already_required[key] = true
73
99
  manager.require_siblings_from_plugin_dir
74
100
  manager.require_siblings_from_gems
75
101
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fusuma
4
- VERSION = "2.5.0"
4
+ VERSION = "3.0.0"
5
5
  end
data/lib/fusuma.rb CHANGED
@@ -13,9 +13,9 @@ module Fusuma
13
13
  class Runner
14
14
  class << self
15
15
  def run(option = {})
16
- set_trap
17
16
  read_options(option)
18
17
  instance = new
18
+ instance.set_trap
19
19
  ## NOTE: Uncomment following line to measure performance
20
20
  # instance.run_with_lineprof
21
21
  instance.run
@@ -23,11 +23,6 @@ module Fusuma
23
23
 
24
24
  private
25
25
 
26
- def set_trap
27
- Signal.trap("INT") { puts exit } # Trap ^C
28
- Signal.trap("TERM") { puts exit } # Trap `Kill `
29
- end
30
-
31
26
  def read_options(option)
32
27
  MultiLogger.filepath = option[:log_filepath]
33
28
  MultiLogger.instance.debug_mode = option[:verbose]
@@ -56,7 +51,9 @@ module Fusuma
56
51
  end
57
52
 
58
53
  def initialize
59
- @inputs = Plugin::Inputs::Input.plugins.map(&:new)
54
+ @inputs = Plugin::Inputs::Input.plugins.map do |cls|
55
+ cls.ancestors.include?(Singleton) ? cls.instance : cls.new
56
+ end
60
57
  @filters = Plugin::Filters::Filter.plugins.map(&:new)
61
58
  @parsers = Plugin::Parsers::Parser.plugins.map(&:new)
62
59
  @buffers = Plugin::Buffers::Buffer.plugins.map(&:new)
@@ -75,8 +72,8 @@ module Fusuma
75
72
  parsed = parse(filtered) || return
76
73
  buffered = buffer(parsed) || return
77
74
  detected = detect(buffered) || return
78
- condition, context, event = merge(detected) || return
79
- execute(condition, context, event)
75
+ context, event = merge(detected) || return
76
+ execute(context, event)
80
77
  end
81
78
 
82
79
  # For performance monitoring
@@ -98,12 +95,14 @@ module Fusuma
98
95
 
99
96
  # @param [Plugin::Events::Event]
100
97
  # @return [Plugin::Events::Event]
98
+ # @return [NilClass]
101
99
  def filter(event)
102
100
  event if @filters.any? { |f| f.filter(event) }
103
101
  end
104
102
 
105
103
  # @param [Plugin::Events::Event]
106
104
  # @return [Plugin::Events::Event]
105
+ # @return [NilClass]
107
106
  def parse(event)
108
107
  @parsers.reduce(event) { |e, p| p.parse(e) if e }
109
108
  end
@@ -117,6 +116,7 @@ module Fusuma
117
116
 
118
117
  # @param buffers [Array<Buffer>]
119
118
  # @return [Array<Event>]
119
+ # @return [NilClass]
120
120
  def detect(buffers)
121
121
  matched_detectors = @detectors.select do |detector|
122
122
  detector.watch? ||
@@ -124,7 +124,8 @@ module Fusuma
124
124
  end
125
125
 
126
126
  events = matched_detectors.each_with_object([]) do |detector, detected|
127
- Array(detector.detect(@buffers)).each { |e| detected << e }
127
+ # Array(detector.detect(@buffers)).each { |e| detected << e }
128
+ detected.concat(Array(detector.detect(@buffers)))
128
129
  end
129
130
 
130
131
  return if events.empty?
@@ -133,7 +134,7 @@ module Fusuma
133
134
  end
134
135
 
135
136
  # @param events [Array<Plugin::Events::Event>]
136
- # @return [Plugin::Events::Event] Event merged all records from arguments
137
+ # @return [Array<Hash, Plugin::Events::Event>] Event merged all events from arguments and used context
137
138
  # @return [NilClass] when event is NOT given
138
139
  def merge(events)
139
140
  index_events, context_events = events.partition { |event| event.record.type == :index }
@@ -143,44 +144,34 @@ module Fusuma
143
144
  end
144
145
  main_events.sort_by! { |e| e.record.trigger_priority }
145
146
 
146
- matched_condition = nil
147
147
  matched_context = nil
148
148
  event = main_events.find do |main_event|
149
149
  matched_context = Config::Searcher.find_context(request_context) do
150
- matched_condition, modified_record = Config::Searcher.find_condition do
151
- main_event.record.merge(records: modifiers.map(&:record))
152
- end
153
- if matched_condition && modified_record
150
+ if modified_record = main_event.record.merge(records: modifiers.map(&:record))
154
151
  main_event.record = modified_record
155
- else
156
- matched_condition, = Config::Searcher.find_condition do
157
- Config.search(main_event.record.index) &&
158
- Config.find_execute_key(main_event.record.index)
159
- end
152
+ elsif !modifiers.empty?
153
+ # try basically the same, but without any modifiers
154
+ # if modifiers is empty then we end up here only if there is no execute key for this
155
+ Config.instance.search(main_event.record.index) &&
156
+ Config.instance.find_execute_key(main_event.record.index)
160
157
  end
161
158
  end
162
159
  end
163
160
  return if event.nil?
164
161
 
165
- [matched_condition, matched_context, event]
162
+ [matched_context, event]
166
163
  end
167
164
 
165
+ # @return [NilClass] when event is NOT given or executable context is NOT found
168
166
  # @param event [Plugin::Events::Event]
169
- def execute(condition, context, event)
167
+ def execute(context, event)
170
168
  return unless event
171
169
 
172
- # Find executable condition and executor
173
- executor = Config::Searcher.with_context(context) do
174
- Config::Searcher.with_condition(condition) do
175
- @executors.find { |e| e.executable?(event) }
176
- end
177
- end
178
-
179
- return if executor.nil?
180
-
181
- # Check interval and execute
170
+ # Find executable context
182
171
  Config::Searcher.with_context(context) do
183
- Config::Searcher.with_condition(condition) do
172
+ executor = @executors.find { |e| e.executable?(event) }
173
+ if executor
174
+ # Check interval and execute
184
175
  executor.enough_interval?(event) &&
185
176
  executor.update_interval(event) &&
186
177
  executor.execute(event)
@@ -191,5 +182,24 @@ module Fusuma
191
182
  def clear_expired_events
192
183
  @buffers.each(&:clear_expired)
193
184
  end
185
+
186
+ def set_trap
187
+ Signal.trap("INT") {
188
+ shutdown
189
+ puts exit
190
+ } # Trap ^C
191
+ Signal.trap("TERM") {
192
+ shutdown
193
+ puts exit
194
+ } # Trap `Kill `
195
+ end
196
+
197
+ private
198
+
199
+ def shutdown
200
+ [@inputs, @filters, @parsers, @buffers, @detectors, @executors].flatten.each do |plugin|
201
+ plugin.shutdown
202
+ end
203
+ end
194
204
  end
195
205
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fusuma
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - iberianpig
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-28 00:00:00.000000000 Z
11
+ date: 2023-08-19 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Fusuma is multitouch gesture recognizer. This gem makes your touchpad
14
14
  on Linux able to recognize swipes or pinchs and assign command to them. Read installation
@@ -86,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
86
  - !ruby/object:Gem::Version
87
87
  version: '0'
88
88
  requirements: []
89
- rubygems_version: 3.0.3.1
89
+ rubygems_version: 3.3.26
90
90
  signing_key:
91
91
  specification_version: 4
92
92
  summary: Multitouch gestures with libinput driver, Linux