fusuma 3.8.1 → 3.10.0

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +27 -1
  3. data/lib/fusuma/config/index.rb +12 -8
  4. data/lib/fusuma/config/searcher.rb +17 -6
  5. data/lib/fusuma/config/yaml_duplication_checker.rb +6 -0
  6. data/lib/fusuma/config.rb +17 -3
  7. data/lib/fusuma/custom_process.rb +4 -1
  8. data/lib/fusuma/device.rb +20 -2
  9. data/lib/fusuma/environment.rb +4 -0
  10. data/lib/fusuma/hash_support.rb +6 -1
  11. data/lib/fusuma/libinput_command.rb +11 -3
  12. data/lib/fusuma/multi_logger.rb +15 -4
  13. data/lib/fusuma/plugin/base.rb +11 -1
  14. data/lib/fusuma/plugin/buffers/buffer.rb +6 -0
  15. data/lib/fusuma/plugin/buffers/gesture_buffer.rb +15 -9
  16. data/lib/fusuma/plugin/buffers/timer_buffer.rb +2 -1
  17. data/lib/fusuma/plugin/detectors/detector.rb +15 -15
  18. data/lib/fusuma/plugin/detectors/hold_detector.rb +10 -2
  19. data/lib/fusuma/plugin/detectors/pinch_detector.rb +13 -1
  20. data/lib/fusuma/plugin/detectors/rotate_detector.rb +11 -0
  21. data/lib/fusuma/plugin/detectors/swipe_detector.rb +12 -0
  22. data/lib/fusuma/plugin/events/event.rb +5 -2
  23. data/lib/fusuma/plugin/events/records/gesture_record.rb +2 -0
  24. data/lib/fusuma/plugin/events/records/index_record.rb +2 -0
  25. data/lib/fusuma/plugin/events/records/record.rb +1 -0
  26. data/lib/fusuma/plugin/events/records/text_record.rb +3 -0
  27. data/lib/fusuma/plugin/executors/command_executor.rb +5 -1
  28. data/lib/fusuma/plugin/executors/executor.rb +6 -0
  29. data/lib/fusuma/plugin/filters/filter.rb +2 -0
  30. data/lib/fusuma/plugin/filters/libinput_device_filter.rb +10 -0
  31. data/lib/fusuma/plugin/inputs/input.rb +5 -0
  32. data/lib/fusuma/plugin/inputs/libinput_command_input.rb +10 -3
  33. data/lib/fusuma/plugin/inputs/timer_input.rb +4 -0
  34. data/lib/fusuma/plugin/manager.rb +11 -1
  35. data/lib/fusuma/plugin/parsers/libinput_gesture_parser.rb +9 -0
  36. data/lib/fusuma/plugin/parsers/parser.rb +4 -0
  37. data/lib/fusuma/string_support.rb +1 -0
  38. data/lib/fusuma/version.rb +1 -1
  39. data/lib/fusuma.rb +11 -2
  40. metadata +2 -2
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "logger"
4
+ require "singleton"
5
+
3
6
  # module as namespace
4
7
  module Fusuma
5
- require "logger"
6
- require "singleton"
7
8
  # logger separate between stdout and strerr
8
9
  class MultiLogger < Logger
9
10
  include Singleton
@@ -14,23 +15,28 @@ module Fusuma
14
15
  class << self
15
16
  attr_writer :filepath
16
17
 
18
+ #: (untyped) -> void
17
19
  def info(msg)
18
20
  instance.info(msg)
19
21
  end
20
22
 
23
+ #: (untyped) -> void
21
24
  def debug(msg)
22
25
  instance.debug(msg)
23
26
  end
24
27
 
28
+ #: (untyped) -> void
25
29
  def warn(msg)
26
30
  instance.warn(msg)
27
31
  end
28
32
 
33
+ #: (untyped) -> void
29
34
  def error(msg)
30
35
  instance.error(msg)
31
36
  end
32
37
  end
33
38
 
39
+ #: () -> void
34
40
  def initialize
35
41
  filepath = self.class.instance_variable_get(:@filepath)
36
42
  if filepath
@@ -45,28 +51,33 @@ module Fusuma
45
51
  @debug_mode = false
46
52
  end
47
53
 
54
+ #: (untyped) -> void
48
55
  def debug(msg)
49
56
  return unless debug_mode?
50
57
 
51
58
  return if ignore_pattern?(msg)
52
59
 
53
- super(msg)
60
+ super
54
61
  end
55
62
 
63
+ #: (untyped) -> void
56
64
  def warn(msg)
57
65
  err_logger.warn(msg)
58
66
  end
59
67
 
68
+ #: (untyped) -> void
60
69
  def error(msg)
61
70
  err_logger.error(msg)
62
71
  end
63
72
 
73
+ #: () -> bool
64
74
  def debug_mode?
65
75
  debug_mode
66
76
  end
67
77
 
68
78
  private
69
79
 
80
+ #: (String) -> bool
70
81
  def ignore_pattern?(msg)
71
82
  # TODO: configurable from config.yml
72
83
  # pattern = /timer_input|remap_touchpad_input|thumbsense context|libinput_command_input/
@@ -74,7 +85,7 @@ module Fusuma
74
85
  case msg
75
86
  when Hash
76
87
  e = msg.values.find { |v| v.is_a? Fusuma::Plugin::Events::Event }
77
- return unless e
88
+ return false unless e
78
89
 
79
90
  e.tag.match?(pattern)
80
91
  when String
@@ -11,7 +11,13 @@ module Fusuma
11
11
  # when inherited from subclass
12
12
  def self.inherited(subclass)
13
13
  super
14
- subclass_path = caller_locations(1..1).first.path
14
+
15
+ locations = Kernel.caller_locations(1..1)
16
+ if locations.nil? || locations.empty?
17
+ raise "Plugin class #{subclass.name} must be defined in a file."
18
+ end
19
+
20
+ subclass_path = locations.first.path
15
21
  Manager.add(plugin_class: subclass, plugin_path: subclass_path)
16
22
  end
17
23
 
@@ -22,11 +28,13 @@ module Fusuma
22
28
  end
23
29
 
24
30
  # @abstract override `#shutdown` to implement
31
+ #: () -> nil
25
32
  def shutdown
26
33
  end
27
34
 
28
35
  # config parameter name and Type of the value of parameter
29
36
  # @return [Hash]
37
+ #: () -> Hash[Symbol, Array[Class] | Class]
30
38
  def config_param_types
31
39
  raise NotImplementedError, "override #{self.class.name}##{__method__}"
32
40
  end
@@ -34,6 +42,7 @@ module Fusuma
34
42
  # @param key [Symbol]
35
43
  # @param base [Config::Index]
36
44
  # @return [Object]
45
+ #: (?Symbol?) -> (String | Hash[untyped, untyped] | Float | bool)?
37
46
  def config_params(key = nil)
38
47
  @config_params ||= {}
39
48
  if @config_params["#{config_index.cache_key},#{key}"]
@@ -59,6 +68,7 @@ module Fusuma
59
68
  end
60
69
  end
61
70
 
71
+ #: () -> Fusuma::Config::Index
62
72
  def config_index
63
73
  @config_index ||= Config::Index.new(self.class.name.gsub("Fusuma::", "").underscore.split("/"))
64
74
  end
@@ -7,6 +7,7 @@ module Fusuma
7
7
  module Buffers
8
8
  # buffer events and output
9
9
  class Buffer < Base
10
+ #: (*nil | Array[untyped]) -> void
10
11
  def initialize(*args)
11
12
  super()
12
13
  @events = Array.new(*args)
@@ -15,11 +16,13 @@ module Fusuma
15
16
  attr_reader :events
16
17
 
17
18
  # @return [String]
19
+ #: () -> String
18
20
  def type
19
21
  @type ||= self.class.name.underscore.split("/").last.gsub("_buffer", "")
20
22
  end
21
23
 
22
24
  # @param event [Event]
25
+ #: (Fusuma::Plugin::Events::Event) -> Array[untyped]?
23
26
  def buffer(event)
24
27
  return if event&.tag != source
25
28
 
@@ -32,17 +35,20 @@ module Fusuma
32
35
  end
33
36
 
34
37
  # @return [TrueClass, FalseClass]
38
+ #: () -> bool
35
39
  def empty?
36
40
  @events.empty?
37
41
  end
38
42
 
39
43
  # clear buffer
44
+ #: () -> void
40
45
  def clear
41
46
  @events.clear
42
47
  end
43
48
 
44
49
  # Set source for tag from config.yml.
45
50
  # DEFAULT_SOURCE is defined in each plugins.
51
+ #: () -> String
46
52
  def source
47
53
  @source ||= config_params(:source) || self.class.const_get(:DEFAULT_SOURCE)
48
54
  end
@@ -11,6 +11,7 @@ module Fusuma
11
11
  DEFAULT_SOURCE = "libinput_gesture_parser"
12
12
  DEFAULT_SECONDS_TO_KEEP = 100
13
13
 
14
+ #: (*nil | Array[untyped]) -> void
14
15
  def initialize(*args)
15
16
  super
16
17
  @cache = {}
@@ -18,6 +19,7 @@ module Fusuma
18
19
  @cache_sum10 = {}
19
20
  end
20
21
 
22
+ #: () -> Hash[untyped, untyped]
21
23
  def clear
22
24
  super.clear
23
25
  @cache = {}
@@ -25,6 +27,7 @@ module Fusuma
25
27
  @cache_sum10 = {}
26
28
  end
27
29
 
30
+ #: () -> Hash[Symbol, Array[Class] | Class]
28
31
  def config_param_types
29
32
  {
30
33
  source: [String],
@@ -34,6 +37,7 @@ module Fusuma
34
37
 
35
38
  # @param event [Event]
36
39
  # @return [Buffer, FalseClass]
40
+ #: (Fusuma::Plugin::Events::Event) -> Fusuma::Plugin::Buffers::GestureBuffer?
37
41
  def buffer(event)
38
42
  # TODO: buffering events into buffer plugins
39
43
  # - gesture event buffer
@@ -45,10 +49,11 @@ module Fusuma
45
49
  self
46
50
  end
47
51
 
52
+ #: (?current_time: Time) -> void
48
53
  def clear_expired(current_time: Time.now)
49
54
  clear if ended?
50
55
 
51
- @seconds_to_keep ||= (config_params(:seconds_to_keep) || DEFAULT_SECONDS_TO_KEEP)
56
+ @seconds_to_keep ||= config_params(:seconds_to_keep) || DEFAULT_SECONDS_TO_KEEP
52
57
  @events.each do |e|
53
58
  break if current_time - e.time < @seconds_to_keep
54
59
 
@@ -61,6 +66,7 @@ module Fusuma
61
66
  end
62
67
  end
63
68
 
69
+ #: () -> bool
64
70
  def ended?
65
71
  return false if empty?
66
72
 
@@ -74,6 +80,7 @@ module Fusuma
74
80
 
75
81
  # @param attr [Symbol]
76
82
  # @return [Float]
83
+ #: (Symbol) -> Float
77
84
  def sum_attrs(attr)
78
85
  updating_events.map do |gesture_event|
79
86
  gesture_event.record.delta[attr].to_f
@@ -82,6 +89,7 @@ module Fusuma
82
89
 
83
90
  # @param attr [Symbol]
84
91
  # @return [Float]
92
+ #: (Symbol) -> Float
85
93
  def sum_last10_attrs(attr) # sums last 10 values of attr (or all if length < 10)
86
94
  cache_entry = (@cache_sum10[attr] ||= CacheEntry.new(0, 0))
87
95
  upd_ev = updating_events
@@ -90,7 +98,7 @@ module Fusuma
90
98
  gesture_event.record.delta[attr].to_f
91
99
  end.reduce(:+)
92
100
  elsif upd_ev.length > cache_entry.checked
93
- cache_entry.value = cache_entry.value + upd_ev[-1].record.delta[attr].to_f - \
101
+ cache_entry.value = cache_entry.value + upd_ev[-1].record.delta[attr].to_f -
94
102
  ((upd_ev.length > 10) ? upd_ev[-11].record.delta[attr].to_f : 0)
95
103
  else
96
104
  return cache_entry.value
@@ -99,6 +107,7 @@ module Fusuma
99
107
  cache_entry.value
100
108
  end
101
109
 
110
+ #: () -> Array[untyped]
102
111
  def updating_events
103
112
  cache_entry = (@cache[:updating_events] ||= CacheEntry.new(0, []))
104
113
  cache_entry.checked.upto(@events.length - 1).each do |i|
@@ -110,11 +119,13 @@ module Fusuma
110
119
 
111
120
  # @param attr [Symbol]
112
121
  # @return [Float]
122
+ #: (Symbol) -> Float
113
123
  def avg_attrs(attr)
114
124
  sum_attrs(attr).to_f / updating_events.length
115
125
  end
116
126
 
117
127
  # return [Integer]
128
+ #: () -> Integer
118
129
  def finger
119
130
  @events.last.record.finger.to_i
120
131
  end
@@ -127,13 +138,7 @@ module Fusuma
127
138
  @events.last.record.gesture
128
139
  end
129
140
 
130
- def select_by_events(&block)
131
- return enum_for(:select_by_events) unless block
132
-
133
- events = @events.select(&block)
134
- self.class.new events
135
- end
136
-
141
+ #: (String) -> Fusuma::Plugin::Buffers::GestureBuffer
137
142
  def select_by_type(type)
138
143
  cache_entry = (@cache_select_by[type] ||= CacheEntry.new(0, self.class.new([])))
139
144
  cache_entry.checked.upto(@events.length - 1).each do |i|
@@ -143,6 +148,7 @@ module Fusuma
143
148
  cache_entry.value
144
149
  end
145
150
 
151
+ #: () -> Fusuma::Plugin::Buffers::GestureBuffer
146
152
  def select_from_last_begin
147
153
  return self if empty?
148
154
  cache_entry = (@cache[:last_begin] ||= CacheEntry.new(0, nil))
@@ -19,6 +19,7 @@ module Fusuma
19
19
 
20
20
  # @param event [Event]
21
21
  # @return [Buffer, NilClass]
22
+ #: (Fusuma::Plugin::Events::Event) -> Fusuma::Plugin::Buffers::TimerBuffer?
22
23
  def buffer(event)
23
24
  return if event&.tag != source
24
25
 
@@ -27,7 +28,7 @@ module Fusuma
27
28
  end
28
29
 
29
30
  def clear_expired(current_time: Time.now)
30
- @seconds_to_keep ||= (config_params(:seconds_to_keep) || DEFAULT_SECONDS_TO_KEEP)
31
+ @seconds_to_keep ||= config_params(:seconds_to_keep) || DEFAULT_SECONDS_TO_KEEP
31
32
  @events.each do |e|
32
33
  break if current_time - e.time < @seconds_to_keep
33
34
 
@@ -8,22 +8,29 @@ module Fusuma
8
8
  module Detectors
9
9
  # Inherite this base
10
10
  class Detector < Base
11
+ def self.type(tag_name)
12
+ tag_name.gsub("_detector", "")
13
+ end
14
+
15
+ #: (*nil) -> void
11
16
  def initialize(*args)
12
17
  super
13
- @tag = self.class.tag
14
- @type = self.class.type
18
+ @tag = self.class.name.split("Detectors::").last.underscore
19
+ @type = self.class.type(@tag)
15
20
  end
16
21
 
17
- attr_reader :tag
18
- attr_reader :type
22
+ attr_reader :tag #: String
23
+ attr_reader :type #: String
19
24
 
20
25
  # @return [Array<String>]
26
+ #: () -> Array[String]
21
27
  def sources
22
28
  @sources ||= self.class.const_get(:SOURCES)
23
29
  end
24
30
 
25
31
  # Always watch buffers and detect them or not
26
32
  # @return [TrueClass,FalseClass]
33
+ #: () -> bool
27
34
  def watch?
28
35
  false
29
36
  end
@@ -39,28 +46,21 @@ module Fusuma
39
46
 
40
47
  # @param record [Events::Records::Record]
41
48
  # @return [Events::Event]
49
+ #: (record: Fusuma::Plugin::Events::Records::IndexRecord) -> Fusuma::Plugin::Events::Event
42
50
  def create_event(record:)
43
51
  @last_time = Time.now
44
- Events::Event.new(time: @last_time, tag: tag, record: record)
52
+ Events::Event.new(time: @last_time, tag: @tag, record: record)
45
53
  end
46
54
 
55
+ #: () -> Time
47
56
  def last_time
48
57
  @last_time ||= Time.now
49
58
  end
50
59
 
60
+ #: () -> bool
51
61
  def first_time?
52
62
  @last_time.nil?
53
63
  end
54
-
55
- class << self
56
- def tag
57
- name.split("Detectors::").last.underscore
58
- end
59
-
60
- def type(tag_name = tag)
61
- tag_name.gsub("_detector", "")
62
- end
63
- end
64
64
  end
65
65
  end
66
66
  end
@@ -14,6 +14,7 @@ module Fusuma
14
14
 
15
15
  BASE_THRESHOLD = 0.7
16
16
 
17
+ #: (*nil) -> void
17
18
  def initialize(*args)
18
19
  super
19
20
  @timer = Inputs::TimerInput.instance
@@ -23,6 +24,7 @@ module Fusuma
23
24
  # @return [Events::Event] if event is detected
24
25
  # @return [Array<Events::Event>] if hold end event is detected
25
26
  # @return [NilClass] if event is NOT detected
27
+ #: (Array[untyped]) -> Fusuma::Plugin::Events::Event?
26
28
  def detect(buffers)
27
29
  hold_buffer = find_hold_buffer(buffers)
28
30
  return if hold_buffer.empty?
@@ -77,6 +79,7 @@ module Fusuma
77
79
 
78
80
  # @param [Integer] finger
79
81
  # @return [Config::Index]
82
+ #: (finger: Integer) -> Fusuma::Config::Index
80
83
  def create_oneshot_index(finger:)
81
84
  Config::Index.new(
82
85
  [
@@ -88,6 +91,7 @@ module Fusuma
88
91
 
89
92
  # @param [Integer] finger
90
93
  # @return [Config::Index]
94
+ #: (finger: Integer, status: String) -> Fusuma::Config::Index
91
95
  def create_repeat_index(finger:, status:)
92
96
  Config::Index.new(
93
97
  [
@@ -102,12 +106,14 @@ module Fusuma
102
106
 
103
107
  # @param buffers [Array<Buffers::Buffer>]
104
108
  # @return [Buffers::GestureBuffer]
109
+ #: (Array[untyped]) -> Fusuma::Plugin::Buffers::GestureBuffer
105
110
  def find_hold_buffer(buffers)
106
111
  buffers.find { |b| b.type == BUFFER_TYPE }
107
112
  .select_from_last_begin
108
113
  .select_by_type(GESTURE_RECORD_TYPE)
109
114
  end
110
115
 
116
+ #: (hold_events: Array[untyped], last_timer: nil | Fusuma::Plugin::Events::Event) -> Float
111
117
  def calc_holding_time(hold_events:, last_timer:)
112
118
  last_time = if last_timer && (hold_events.last.time < last_timer.time)
113
119
  last_timer.time
@@ -117,16 +123,18 @@ module Fusuma
117
123
  last_time - hold_events.first.time
118
124
  end
119
125
 
126
+ #: (index: Fusuma::Config::Index, holding_time: Float) -> bool
120
127
  def enough?(index:, holding_time:)
121
128
  diff = threshold(index: index) - holding_time
122
129
  if diff < 0
123
- true
130
+ return true
124
131
  elsif diff < @timer.interval
125
132
  @timer.wake_early(Time.now + diff)
126
- false
127
133
  end
134
+ false
128
135
  end
129
136
 
137
+ #: (index: Fusuma::Config::Index) -> Float
130
138
  def threshold(index:)
131
139
  @threshold ||= {}
132
140
  @threshold[index.cache_key] ||= begin
@@ -16,6 +16,7 @@ module Fusuma
16
16
  # @param buffers [Array<Buffer>]
17
17
  # @return [Events::Event] if event is detected
18
18
  # @return [NilClass] if event is NOT detected
19
+ #: (Array[untyped]) -> (Fusuma::Plugin::Events::Event | Array[untyped])?
19
20
  def detect(buffers)
20
21
  gesture_buffer = buffers.find { |b| b.type == BUFFER_TYPE }
21
22
  .select_from_last_begin
@@ -53,7 +54,7 @@ module Fusuma
53
54
  delta = event.record.delta
54
55
  prev_delta = prev_event.record.delta
55
56
 
56
- repeat_direction = Direction.new(target: delta.zoom, base: (prev_delta&.zoom || 1.0)).to_s
57
+ repeat_direction = Direction.new(target: delta.zoom, base: prev_delta&.zoom || 1.0).to_s
57
58
  # repeat_quantity = Quantity.new(target: delta.zoom, base: (prev_delta&.zoom || 1.0)).to_f
58
59
 
59
60
  repeat_index = create_repeat_index(gesture: type, finger: finger,
@@ -97,6 +98,7 @@ module Fusuma
97
98
  # @param [String] direction
98
99
  # @param [String] status
99
100
  # @return [Config::Index]
101
+ #: (gesture: String, finger: Integer, direction: String, status: String) -> Fusuma::Config::Index
100
102
  def create_repeat_index(gesture:, finger:, direction:, status:)
101
103
  Config::Index.new(
102
104
  [
@@ -112,6 +114,7 @@ module Fusuma
112
114
  # @param [Integer] finger
113
115
  # @param [String] direction
114
116
  # @return [Config::Index]
117
+ #: (gesture: String, finger: Integer, direction: String) -> Fusuma::Config::Index
115
118
  def create_oneshot_index(gesture:, finger:, direction:)
116
119
  Config::Index.new(
117
120
  [
@@ -124,16 +127,19 @@ module Fusuma
124
127
 
125
128
  private
126
129
 
130
+ #: (Fusuma::Plugin::Events::Event, Fusuma::Plugin::Events::Event) -> bool
127
131
  def moved?(prev_event, event)
128
132
  zoom_delta = (event.record.delta.zoom - prev_event.record.delta.zoom).abs
129
133
  updating_time = (event.time - prev_event.time) * 100
130
134
  zoom_delta / updating_time > 0.01
131
135
  end
132
136
 
137
+ #: (index: Fusuma::Config::Index, quantity: Float) -> bool
133
138
  def enough_oneshot_threshold?(index:, quantity:)
134
139
  quantity >= threshold(index: index)
135
140
  end
136
141
 
142
+ #: (index: Fusuma::Config::Index) -> Float
137
143
  def threshold(index:)
138
144
  @threshold ||= {}
139
145
  @threshold[index.cache_key] ||= begin
@@ -150,15 +156,18 @@ module Fusuma
150
156
  IN = "in"
151
157
  OUT = "out"
152
158
 
159
+ #: (target: Float, base: Integer | Float) -> void
153
160
  def initialize(target:, base:)
154
161
  @target = target.to_f
155
162
  @base = base.to_f
156
163
  end
157
164
 
165
+ #: () -> String
158
166
  def to_s
159
167
  calc
160
168
  end
161
169
 
170
+ #: () -> String
162
171
  def calc
163
172
  if @target > @base
164
173
  OUT
@@ -170,15 +179,18 @@ module Fusuma
170
179
 
171
180
  # quantity of gesture
172
181
  class Quantity
182
+ #: (target: Float, base: Float) -> void
173
183
  def initialize(target:, base:)
174
184
  @target = target.to_f
175
185
  @base = base.to_f
176
186
  end
177
187
 
188
+ #: () -> Float
178
189
  def to_f
179
190
  calc.to_f
180
191
  end
181
192
 
193
+ #: () -> Float
182
194
  def calc
183
195
  if @target > @base
184
196
  @target / @base
@@ -16,6 +16,7 @@ module Fusuma
16
16
  # @param buffers [Array<Buffer>]
17
17
  # @return [Events::Event] if event is detected
18
18
  # @return [NilClass] if event is NOT detected
19
+ #: (Array[untyped]) -> (Fusuma::Plugin::Events::Event | Array[untyped])?
19
20
  def detect(buffers)
20
21
  gesture_buffer = buffers.find { |b| b.type == BUFFER_TYPE }
21
22
  .select_from_last_begin
@@ -84,6 +85,7 @@ module Fusuma
84
85
  # @param [String] direction
85
86
  # @param [String] status
86
87
  # @return [Config::Index]
88
+ #: (gesture: String, finger: Integer, direction: String, status: String) -> Fusuma::Config::Index
87
89
  def create_repeat_index(gesture:, finger:, direction:, status:)
88
90
  Config::Index.new(
89
91
  [
@@ -99,6 +101,7 @@ module Fusuma
99
101
  # @param [Integer] finger
100
102
  # @param [String] direction
101
103
  # @return [Config::Index]
104
+ #: (gesture: String, finger: Integer, direction: String) -> Fusuma::Config::Index
102
105
  def create_oneshot_index(gesture:, finger:, direction:)
103
106
  Config::Index.new(
104
107
  [
@@ -111,14 +114,17 @@ module Fusuma
111
114
 
112
115
  private
113
116
 
117
+ #: (Float) -> bool
114
118
  def moved?(repeat_quantity)
115
119
  repeat_quantity > 0.2
116
120
  end
117
121
 
122
+ #: (index: Fusuma::Config::Index, quantity: Float) -> bool
118
123
  def enough_oneshot_threshold?(index:, quantity:)
119
124
  quantity > threshold(index: index)
120
125
  end
121
126
 
127
+ #: (index: Fusuma::Config::Index) -> Float
122
128
  def threshold(index:)
123
129
  @threshold ||= {}
124
130
  @threshold[index.cache_key] ||= begin
@@ -135,14 +141,17 @@ module Fusuma
135
141
  CLOCKWISE = "clockwise"
136
142
  COUNTERCLOCKWISE = "counterclockwise"
137
143
 
144
+ #: (angle: Float) -> void
138
145
  def initialize(angle:)
139
146
  @angle = angle.to_f
140
147
  end
141
148
 
149
+ #: () -> String
142
150
  def to_s
143
151
  calc
144
152
  end
145
153
 
154
+ #: () -> String
146
155
  def calc
147
156
  if @angle.positive?
148
157
  CLOCKWISE
@@ -154,10 +163,12 @@ module Fusuma
154
163
 
155
164
  # quantity of gesture
156
165
  class Quantity
166
+ #: (angle: Float) -> void
157
167
  def initialize(angle:)
158
168
  @angle = angle.abs
159
169
  end
160
170
 
171
+ #: () -> Float
161
172
  def to_f
162
173
  @angle.to_f
163
174
  end
@@ -16,6 +16,7 @@ module Fusuma
16
16
  # @param buffers [Array<Buffers::Buffer>]
17
17
  # @return [Events::Event] if event is detected
18
18
  # @return [NilClass] if event is NOT detected
19
+ #: (Array[untyped]) -> (Fusuma::Plugin::Events::Event | Array[untyped])?
19
20
  def detect(buffers)
20
21
  gesture_buffer = buffers.find { |b| b.type == BUFFER_TYPE }
21
22
  .select_from_last_begin
@@ -82,6 +83,7 @@ module Fusuma
82
83
  # @param [String] direction
83
84
  # @param [String] status
84
85
  # @return [Config::Index]
86
+ #: (gesture: String, finger: Integer, direction: String, status: String) -> Fusuma::Config::Index
85
87
  def create_repeat_index(gesture:, finger:, direction:, status:)
86
88
  Config::Index.new(
87
89
  [
@@ -97,6 +99,7 @@ module Fusuma
97
99
  # @param [Integer] finger
98
100
  # @param [String] direction
99
101
  # @return [Config::Index]
102
+ #: (gesture: String, finger: Integer, direction: String) -> Fusuma::Config::Index
100
103
  def create_oneshot_index(gesture:, finger:, direction:)
101
104
  Config::Index.new(
102
105
  [
@@ -109,14 +112,17 @@ module Fusuma
109
112
 
110
113
  private
111
114
 
115
+ #: (Float) -> bool
112
116
  def moved?(repeat_quantity)
113
117
  repeat_quantity > 0.3
114
118
  end
115
119
 
120
+ #: (index: Fusuma::Config::Index, quantity: Float) -> bool
116
121
  def enough_oneshot_threshold?(index:, quantity:)
117
122
  quantity > threshold(index: index)
118
123
  end
119
124
 
125
+ #: (index: Fusuma::Config::Index) -> Integer
120
126
  def threshold(index:)
121
127
  @threshold ||= {}
122
128
  @threshold[index.cache_key] ||= begin
@@ -135,15 +141,18 @@ module Fusuma
135
141
  DOWN = "down"
136
142
  UP = "up"
137
143
 
144
+ #: (move_x: Integer | Float, move_y: Integer | Float) -> void
138
145
  def initialize(move_x:, move_y:)
139
146
  @move_x = move_x.to_f
140
147
  @move_y = move_y.to_f
141
148
  end
142
149
 
150
+ #: () -> String
143
151
  def to_s
144
152
  calc
145
153
  end
146
154
 
155
+ #: () -> String
147
156
  def calc
148
157
  if @move_x.abs > @move_y.abs
149
158
  @move_x.positive? ? RIGHT : LEFT
@@ -157,15 +166,18 @@ module Fusuma
157
166
 
158
167
  # quantity of gesture
159
168
  class Quantity
169
+ #: (move_x: Integer | Float, move_y: Integer | Float) -> void
160
170
  def initialize(move_x:, move_y:)
161
171
  @x = move_x.to_f.abs
162
172
  @y = move_y.to_f.abs
163
173
  end
164
174
 
175
+ #: () -> Float
165
176
  def to_f
166
177
  calc.to_f
167
178
  end
168
179
 
180
+ #: () -> Float
169
181
  def calc
170
182
  (@x > @y) ? @x.abs : @y.abs
171
183
  end