fusuma 3.9.0 → 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 -7
  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 +3 -0
  8. data/lib/fusuma/device.rb +15 -0
  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 +10 -1
  40. metadata +2 -2
@@ -10,11 +10,13 @@ module Fusuma
10
10
  # Event format
11
11
  class Event < Base
12
12
  attr_reader :time
13
- attr_accessor :tag, :record
13
+ attr_accessor :tag #: String
14
+ attr_accessor :record #: Records::Record
14
15
 
15
16
  # @param time [Time]
16
17
  # @param tag [Tag]
17
18
  # @param record [String, Record]
19
+ #: (tag: String, record: String | Fusuma::Plugin::Events::Records::Record, ?time: Time | nil) -> void
18
20
  def initialize(tag:, record:, time: Time.now)
19
21
  super()
20
22
  @time = time
@@ -30,8 +32,9 @@ module Fusuma
30
32
  end
31
33
  end
32
34
 
35
+ #: () -> String
33
36
  def inspect
34
- "tag: #{tag}, record: #{record}"
37
+ "tag: #{@tag}, record: #{@record}"
35
38
  end
36
39
  end
37
40
  end
@@ -22,6 +22,7 @@ module Fusuma
22
22
  # @param gesture [String]
23
23
  # @param finger [String, Integer]
24
24
  # @param delta [Delta, NilClass]
25
+ #: (status: String, gesture: String, finger: Integer | String, delta: Fusuma::Plugin::Events::Records::GestureRecord::Delta | nil) -> void
25
26
  def initialize(status:, gesture:, finger:, delta:)
26
27
  super()
27
28
  @status = status
@@ -30,6 +31,7 @@ module Fusuma
30
31
  @delta = delta
31
32
  end
32
33
 
34
+ #: () -> String
33
35
  def to_s
34
36
  "#{@gesture}, Finger: #{@finger}, Status: #{@status}"
35
37
  end
@@ -14,6 +14,7 @@ module Fusuma
14
14
  # @param [Config::Index] index
15
15
  # @param [Symbol] position [:prefix, :body, :surfix]
16
16
  # @param [Symbol] trigger [:oneshot, :repeat]
17
+ #: (index: Fusuma::Config::Index, ?position: Symbol, ?trigger: Symbol, ?args: Hash[untyped, untyped]) -> void
17
18
  def initialize(index:, position: :body, trigger: :oneshot, args: {})
18
19
  super()
19
20
  @index = index
@@ -26,6 +27,7 @@ module Fusuma
26
27
  "#{@index}, #{@position}, #{@trigger}, #{@args}"
27
28
  end
28
29
 
30
+ #: () -> Symbol
29
31
  def type
30
32
  :index
31
33
  end
@@ -10,6 +10,7 @@ module Fusuma
10
10
  # @abstract Subclass and override {#type} to implement
11
11
  class Record < Base
12
12
  # @return [Symbol]
13
+ #: () -> nil
13
14
  def type
14
15
  raise NotImplementedError, "override #type"
15
16
  end
@@ -9,16 +9,19 @@ module Fusuma
9
9
  # Default Record
10
10
  class TextRecord < Record
11
11
  # @param text [String]
12
+ #: (String) -> void
12
13
  def initialize(text)
13
14
  super()
14
15
  @text = text
15
16
  end
16
17
 
18
+ #: () -> Symbol
17
19
  def type
18
20
  :text
19
21
  end
20
22
 
21
23
  # @return [String]
24
+ #: () -> String
22
25
  def to_s
23
26
  @text
24
27
  end
@@ -13,6 +13,7 @@ module Fusuma
13
13
  [:command]
14
14
  end
15
15
 
16
+ #: (Fusuma::Plugin::Events::Event) -> void
16
17
  def execute(event)
17
18
  command = search_command(event)
18
19
 
@@ -26,9 +27,10 @@ module Fusuma
26
27
  pid = Process.spawn(additional_env, command.to_s)
27
28
  Process.detach(pid)
28
29
  rescue SystemCallError => e
29
- MultiLogger.error("#{event.record.index.keys}": e.message.to_s)
30
+ MultiLogger.error("#{event.record.index.keys}: #{e.message}")
30
31
  end
31
32
 
33
+ #: (Fusuma::Plugin::Events::Event) -> (String | bool)
32
34
  def executable?(event)
33
35
  event.tag.end_with?("_detector") &&
34
36
  event.record.type == :index &&
@@ -37,6 +39,7 @@ module Fusuma
37
39
 
38
40
  # @param event [Event]
39
41
  # @return [String]
42
+ #: (Fusuma::Plugin::Events::Event) -> String
40
43
  def search_command(event)
41
44
  command_index = Config::Index.new([*event.record.index.keys, :command])
42
45
  Config.instance.search(command_index)
@@ -44,6 +47,7 @@ module Fusuma
44
47
 
45
48
  # @param event [Event]
46
49
  # @return [Float]
50
+ #: (Fusuma::Plugin::Events::Event) -> Float
47
51
  def args_accel(event)
48
52
  accel_index = Config::Index.new([*event.record.index.keys, :accel])
49
53
  (Config.instance.search(accel_index) || 1).to_f
@@ -13,6 +13,7 @@ module Fusuma
13
13
 
14
14
  # Executor parameter on config.yml
15
15
  # @return [Array<Symbol>]
16
+ #: () -> nil
16
17
  def execute_keys
17
18
  # [name.split('Executors::').last.underscore.gsub('_executor', '').to_sym]
18
19
  raise NotImplementedError, "override #{self.class.name}##{__method__}"
@@ -21,12 +22,14 @@ module Fusuma
21
22
  # check executable
22
23
  # @param _event [Events::Event]
23
24
  # @return [TrueClass, FalseClass]
25
+ #: (String) -> nil
24
26
  def executable?(_event)
25
27
  raise NotImplementedError, "override #{self.class.name}##{__method__}"
26
28
  end
27
29
 
28
30
  # @param event [Events::Event]
29
31
  # @return [TrueClass, FalseClass]
32
+ #: (Fusuma::Plugin::Events::Event) -> bool
30
33
  def enough_interval?(event)
31
34
  return true if event.record.index.keys.any? { |key| key.symbol == :end }
32
35
 
@@ -35,10 +38,12 @@ module Fusuma
35
38
  true
36
39
  end
37
40
 
41
+ #: (Fusuma::Plugin::Events::Event) -> Time
38
42
  def update_interval(event)
39
43
  @wait_until = event.time + interval(event).to_f
40
44
  end
41
45
 
46
+ #: (Fusuma::Plugin::Events::Event) -> Float
42
47
  def interval(event)
43
48
  @interval_time ||= {}
44
49
  index = event.record.index
@@ -57,6 +62,7 @@ module Fusuma
57
62
  # execute something
58
63
  # @param _event [Event]
59
64
  # @return [nil]
65
+ #: (String) -> nil
60
66
  def execute(_event)
61
67
  raise NotImplementedError, "override #{self.class.name}##{__method__}"
62
68
  end
@@ -11,6 +11,7 @@ module Fusuma
11
11
  # @param event [Event]
12
12
  # @return [Event] when keeping event
13
13
  # @return [NilClass] when discarding record
14
+ #: (Fusuma::Plugin::Events::Event) -> Fusuma::Plugin::Events::Event?
14
15
  def filter(event)
15
16
  return event if !/#{source}/.match?(event.tag)
16
17
 
@@ -29,6 +30,7 @@ module Fusuma
29
30
 
30
31
  # Set source for tag from config.yml.
31
32
  # DEFAULT_SOURCE is defined in each Filter plugins.
33
+ #: () -> String
32
34
  def source
33
35
  @source ||= config_params(:source) || self.class.const_get(:DEFAULT_SOURCE)
34
36
  end
@@ -10,6 +10,7 @@ module Fusuma
10
10
  class LibinputDeviceFilter < Filter
11
11
  DEFAULT_SOURCE = "libinput_command_input"
12
12
 
13
+ #: () -> Hash[Symbol, Array[Class] | Class]
13
14
  def config_param_types
14
15
  {
15
16
  source: String,
@@ -19,6 +20,7 @@ module Fusuma
19
20
 
20
21
  # @return [TrueClass] when keeping it
21
22
  # @return [FalseClass] when discarding it
23
+ #: (Fusuma::Plugin::Events::Records::TextRecord) -> bool
22
24
  def keep?(record)
23
25
  # NOTE: purge cache when found new device
24
26
  if record.to_s =~ /\sDEVICE_ADDED\s/ && keep_device.match_pattern?(record.to_s)
@@ -29,6 +31,7 @@ module Fusuma
29
31
  keep_device.all.map(&:id).include?(device_id)
30
32
  end
31
33
 
34
+ #: () -> Fusuma::Plugin::Filters::LibinputDeviceFilter::KeepDevice
32
35
  def keep_device
33
36
  @keep_device ||= begin
34
37
  from_config = Array(config_params(:keep_device_names))
@@ -36,6 +39,7 @@ module Fusuma
36
39
  end
37
40
  end
38
41
 
42
+ #: () -> String
39
43
  def config_param_sample
40
44
  <<~SAMPLE
41
45
  ```config.yml
@@ -50,6 +54,7 @@ module Fusuma
50
54
 
51
55
  # Select Device to keep
52
56
  class KeepDevice
57
+ #: (name_patterns: Array[untyped]) -> void
53
58
  def initialize(name_patterns:)
54
59
  @name_patterns = name_patterns | Array(self.class.from_option)
55
60
  end
@@ -57,12 +62,14 @@ module Fusuma
57
62
  attr_reader :name_patterns
58
63
 
59
64
  # remove cache for reloading new devices
65
+ #: () -> void
60
66
  def reset
61
67
  @all = nil
62
68
  Device.reset
63
69
  end
64
70
 
65
71
  # @return [Array]
72
+ #: () -> Array[Device]
66
73
  def all
67
74
  @all ||= if @name_patterns.empty?
68
75
  Device.available
@@ -75,6 +82,7 @@ module Fusuma
75
82
  end
76
83
  end
77
84
 
85
+ #: () -> nil
78
86
  def print_not_found_messages
79
87
  puts "Device is not found. Check following section on your config.yml"
80
88
  puts LibinputDeviceFilter.new.config_param_sample
@@ -82,6 +90,7 @@ module Fusuma
82
90
 
83
91
  # @return [TrueClass]
84
92
  # @return [FalseClass]
93
+ #: (String) -> bool
85
94
  def match_pattern?(string)
86
95
  return true if @name_patterns.empty?
87
96
 
@@ -92,6 +101,7 @@ module Fusuma
92
101
  attr_reader :from_option
93
102
 
94
103
  # TODO: remove from_option and command line options
104
+ #: (nil) -> void
95
105
  def from_option=(device)
96
106
  if device
97
107
  warn <<~COMMENT
@@ -9,6 +9,7 @@ module Fusuma
9
9
  # Inherite this base
10
10
  # @abstract Subclass and override {#io} to implement
11
11
  class Input < Base
12
+ #: (*nil) -> void
12
13
  def initialize(*args)
13
14
  super
14
15
  @tag = self.class.name.split("Inputs::").last.underscore
@@ -19,6 +20,7 @@ module Fusuma
19
20
  # Wait multiple inputs until it becomes readable
20
21
  # @param inputs [Array<Input>]
21
22
  # @return [Event]
23
+ #: (Array[untyped]) -> Fusuma::Plugin::Events::Event
22
24
  def self.select(inputs)
23
25
  ios = IO.select(inputs.map(&:io))
24
26
  io = ios&.first&.first
@@ -32,6 +34,7 @@ module Fusuma
32
34
  # IO#readline is blocking method
33
35
  # so input plugin must write line to pipe (include `\n`)
34
36
  # or, override read_from_io and implement your own read method
37
+ #: () -> String
35
38
  def read_from_io
36
39
  io.readline(chomp: true)
37
40
  rescue EOFError => e
@@ -44,11 +47,13 @@ module Fusuma
44
47
  end
45
48
 
46
49
  # @return [IO]
50
+ #: () -> nil
47
51
  def io
48
52
  raise NotImplementedError, "override #{self.class.name}##{__method__}"
49
53
  end
50
54
 
51
55
  # @return [Event]
56
+ #: (?record: String) -> Fusuma::Plugin::Events::Event
52
57
  def create_event(record: "dummy input")
53
58
  e = Events::Event.new(tag: tag, record: record)
54
59
  MultiLogger.debug(input_event: e)
@@ -8,6 +8,7 @@ module Fusuma
8
8
  module Inputs
9
9
  # libinput commands wrapper
10
10
  class LibinputCommandInput < Input
11
+ #: () -> Hash[Symbol, Array[Class]]
11
12
  def config_param_types
12
13
  {
13
14
  device: [String],
@@ -23,6 +24,7 @@ module Fusuma
23
24
  end
24
25
 
25
26
  # @return [IO]
27
+ #: () -> StringIO
26
28
  def io
27
29
  @io ||= begin
28
30
  reader, writer = create_io
@@ -32,6 +34,7 @@ module Fusuma
32
34
  end
33
35
 
34
36
  # @return [LibinputCommand]
37
+ #: () -> (Fusuma::LibinputCommand)
35
38
  def command
36
39
  @command ||= LibinputCommand.new(
37
40
  libinput_options: libinput_options,
@@ -44,6 +47,7 @@ module Fusuma
44
47
  end
45
48
 
46
49
  # @return [Array]
50
+ #: () -> Array[String]
47
51
  def libinput_options
48
52
  device = ("--device='#{config_params(:device)}'" if config_params(:device))
49
53
  enable_tap = "--enable-tap" if config_params(:"enable-tap")
@@ -61,15 +65,18 @@ module Fusuma
61
65
  ].compact
62
66
  end
63
67
 
64
- def libinput_command
68
+ #: () -> String?
69
+ def libinput_command # steep:ignore MethodBodyTypeMismatch
65
70
  config_params(:"libinput-command")
66
71
  end
67
72
 
68
- def debug_events_command
73
+ #: () -> String?
74
+ def debug_events_command # steep:ignore MethodBodyTypeMismatch
69
75
  config_params(:"libinput-debug-events")
70
76
  end
71
77
 
72
- def list_devices_command
78
+ #: () -> String?
79
+ def list_devices_command # steep:ignore MethodBodyTypeMismatch
73
80
  config_params(:"libinput-list-devices")
74
81
  end
75
82
 
@@ -17,6 +17,7 @@ module Fusuma
17
17
  }
18
18
  end
19
19
 
20
+ #: (*nil, ?interval: nil) -> void
20
21
  def initialize(*args, interval: nil)
21
22
  super(*args)
22
23
  @interval = interval || config_params(:interval) || DEFAULT_INTERVAL
@@ -25,6 +26,7 @@ module Fusuma
25
26
 
26
27
  attr_reader :interval
27
28
 
29
+ #: () -> IO
28
30
  def io
29
31
  @io ||= begin
30
32
  reader, writer = create_io
@@ -34,6 +36,7 @@ module Fusuma
34
36
  end
35
37
  end
36
38
 
39
+ #: (IO, IO) -> Thread
37
40
  def start(reader, writer)
38
41
  Thread.new do
39
42
  timer_loop(writer)
@@ -62,6 +65,7 @@ module Fusuma
62
65
  MultiLogger.error e
63
66
  end
64
67
 
68
+ #: (Time) -> Thread::Queue
65
69
  def wake_early(t)
66
70
  @early_wake_queue.push(t + EPSILON_TIME)
67
71
  end
@@ -7,22 +7,27 @@ module Fusuma
7
7
  module Plugin
8
8
  # Manage Fusuma plugins
9
9
  class Manager
10
+ #: (Class) -> void
10
11
  def initialize(plugin_class)
11
12
  @plugin_class = plugin_class
12
13
  end
13
14
 
15
+ #: () -> Array[untyped]
14
16
  def require_siblings_from_plugin_dir
15
17
  fusuma_default_plugin_paths.each { |siblings_plugin| require(siblings_plugin) }
16
18
  end
17
19
 
20
+ #: () -> Array[untyped]
18
21
  def require_siblings_from_gems
19
22
  fusuma_external_plugin_paths.each { |siblings_plugin| require(siblings_plugin) }
20
23
  end
21
24
 
25
+ #: () -> Regexp
22
26
  def exclude_path_pattern
23
27
  %r{fusuma/plugin/[^/]*.rb}
24
28
  end
25
29
 
30
+ #: () -> Array[untyped]
26
31
  def fusuma_default_plugin_paths
27
32
  @_fusuma_default_plugin_paths ||= Dir.glob(File.expand_path("#{__dir__}/../../#{search_key}")).grep_v(exclude_path_pattern).sort
28
33
  end
@@ -38,7 +43,7 @@ module Fusuma
38
43
  raise "Not Found: #{match_data[1]}/#{match_data[2]}/*.gemspec" unless plugin_gemspec_path
39
44
 
40
45
  plugin_gemspec = Gem::Specification.load(plugin_gemspec_path)
41
- fusuma_gemspec_path = File.expand_path("../../../fusuma.gemspec", __dir__)
46
+ fusuma_gemspec_path = File.expand_path("../../../fusuma.gemspec", __dir__ || ".")
42
47
  fusuma_gemspec = Gem::Specification.load(fusuma_gemspec_path)
43
48
  next if plugin_gemspec == fusuma_gemspec
44
49
 
@@ -56,6 +61,7 @@ module Fusuma
56
61
  # @example
57
62
  # search_key
58
63
  # => "fusuma/plugin/detectors/*rb"
64
+ #: () -> String
59
65
  def search_key
60
66
  File.join(plugin_dir_name, "*rb")
61
67
  end
@@ -66,6 +72,7 @@ module Fusuma
66
72
  # plugin_dir_name
67
73
  # => "fusuma/plugin/detectors"
68
74
  # @return [String]
75
+ #: () -> String
69
76
  def plugin_dir_name
70
77
  @plugin_class.name.match(/(Fusuma::.*)::/)[1].to_s.underscore
71
78
  end
@@ -101,6 +108,7 @@ module Fusuma
101
108
  manager.require_siblings_from_gems
102
109
  end
103
110
 
111
+ #: () -> void
104
112
  def require_base_plugins
105
113
  require_relative "base"
106
114
  require_relative "events/event"
@@ -112,6 +120,7 @@ module Fusuma
112
120
  require_relative "executors/executor"
113
121
  end
114
122
 
123
+ #: () -> Hash[untyped, untyped]
115
124
  def plugins
116
125
  @plugins ||= {}
117
126
  end
@@ -122,6 +131,7 @@ module Fusuma
122
131
  # => ["/path/to/fusuma/lib/fusuma/plugin/inputs/input.rb",
123
132
  # "/path/to/fusuma/lib/fusuma/plugin/inputs/libinput_command_input.rb",
124
133
  # "/path/to/fusuma/lib/fusuma/plugin/inputs/timer_input.rb"]
134
+ #: () -> Array[untyped]
125
135
  def load_paths
126
136
  @load_paths ||= []
127
137
  end
@@ -13,6 +13,7 @@ module Fusuma
13
13
 
14
14
  # @param record [String]
15
15
  # @return [Records::GestureRecord, nil]
16
+ #: (Fusuma::Plugin::Events::Records::TextRecord) -> Fusuma::Plugin::Events::Records::GestureRecord?
16
17
  def parse_record(record)
17
18
  case line = record.to_s
18
19
  when /GESTURE_SWIPE|GESTURE_PINCH|GESTURE_HOLD/
@@ -29,6 +30,7 @@ module Fusuma
29
30
 
30
31
  private
31
32
 
33
+ #: (String) -> Array[untyped]
32
34
  def parse_libinput(line)
33
35
  if libinput_1_27_0_or_later?
34
36
  parse_line_1_27_0_or_later(line)
@@ -37,16 +39,19 @@ module Fusuma
37
39
  end
38
40
  end
39
41
 
42
+ #: () -> bool
40
43
  def libinput_1_27_0_or_later?
41
44
  return @libinput_1_27_0_or_later if defined?(@libinput_1_27_0_or_later)
42
45
 
43
46
  @libinput_1_27_0_or_later = Inputs::LibinputCommandInput.new.command.libinput_1_27_0_or_later?
44
47
  end
45
48
 
49
+ #: (String) -> Array[untyped]
46
50
  def parse_line(line)
47
51
  _device, event_name, _time, other = line.strip.split(nil, 4)
48
52
  finger, other = other.split(nil, 2)
49
53
 
54
+ return [] unless event_name
50
55
  gesture, status = *detect_gesture(event_name)
51
56
 
52
57
  status = "cancelled" if gesture == "hold" && status == "end" && other == "cancelled"
@@ -54,6 +59,7 @@ module Fusuma
54
59
  [gesture, status, finger, delta]
55
60
  end
56
61
 
62
+ #: (String) -> Array[untyped]
57
63
  def parse_line_1_27_0_or_later(line)
58
64
  _device, event_name, other = line.strip.split(nil, 3)
59
65
 
@@ -63,6 +69,7 @@ module Fusuma
63
69
 
64
70
  _time, finger, other = other.split(nil, 3)
65
71
 
72
+ return [] unless event_name
66
73
  gesture, status = *detect_gesture(event_name)
67
74
 
68
75
  status = "cancelled" if gesture == "hold" && status == "end" && other == "cancelled"
@@ -70,6 +77,7 @@ module Fusuma
70
77
  [gesture, status, finger, delta]
71
78
  end
72
79
 
80
+ #: (String) -> Array[untyped]
73
81
  def detect_gesture(event_name)
74
82
  event_name =~ /GESTURE_(SWIPE|PINCH|HOLD)_(BEGIN|UPDATE|END)/
75
83
  gesture = Regexp.last_match(1).downcase
@@ -77,6 +85,7 @@ module Fusuma
77
85
  [gesture, status]
78
86
  end
79
87
 
88
+ #: (String?) -> Fusuma::Plugin::Events::Records::GestureRecord::Delta?
80
89
  def parse_delta(line)
81
90
  return if line.nil?
82
91
 
@@ -12,6 +12,7 @@ module Fusuma
12
12
  # if `#parse_record` return nil, this method will return original event
13
13
  # @param event [Event]
14
14
  # @return [Event]
15
+ #: (Fusuma::Plugin::Events::Event) -> Fusuma::Plugin::Events::Event
15
16
  def parse(event)
16
17
  return event if event.tag != source
17
18
 
@@ -25,10 +26,12 @@ module Fusuma
25
26
 
26
27
  # Set source for tag from config.yml.
27
28
  # DEFAULT_SOURCE is defined in each Parser plugins.
29
+ #: () -> String
28
30
  def source
29
31
  @source ||= config_params(:source) || self.class.const_get(:DEFAULT_SOURCE)
30
32
  end
31
33
 
34
+ #: () -> String
32
35
  def tag
33
36
  @tag ||= self.class.name.split("::").last.underscore
34
37
  end
@@ -36,6 +39,7 @@ module Fusuma
36
39
  # parse Record object
37
40
  # @param _record [Record]
38
41
  # @return [Record, nil]
42
+ #: (Fusuma::Plugin::Events::Records::Record) -> Fusuma::Plugin::Events::Records::Record?
39
43
  def parse_record(_record)
40
44
  nil
41
45
  end
@@ -6,6 +6,7 @@ class String
6
6
  split("_").map(&:capitalize).join
7
7
  end
8
8
 
9
+ #: () -> String
9
10
  def underscore
10
11
  gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
11
12
  .gsub(/([a-z\d])([A-Z])/, '\1_\2')
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fusuma
4
- VERSION = "3.9.0"
4
+ VERSION = "3.10.0"
5
5
  end
data/lib/fusuma.rb CHANGED
@@ -12,6 +12,7 @@ module Fusuma
12
12
  # main class
13
13
  class Runner
14
14
  class << self
15
+ #: (?Hash[untyped, untyped]) -> void
15
16
  def run(option = {})
16
17
  read_options(option)
17
18
  instance = new
@@ -26,6 +27,7 @@ module Fusuma
26
27
 
27
28
  private
28
29
 
30
+ #: (Hash[untyped, untyped]) -> void
29
31
  def read_options(option)
30
32
  MultiLogger.filepath = option[:log_filepath]
31
33
  MultiLogger.instance.debug_mode = option[:verbose]
@@ -53,13 +55,17 @@ module Fusuma
53
55
  Process.daemon if option[:daemon]
54
56
  end
55
57
 
58
+ #: (String?) -> void
56
59
  def load_custom_config(config_path = nil)
57
60
  Config.custom_path = config_path
58
61
  end
59
62
  end
60
63
 
61
- def initialize; end
64
+ #: () -> void
65
+ def initialize
66
+ end
62
67
 
68
+ #: () -> void
63
69
  def initialize_plugins
64
70
  @inputs = Plugin::Inputs::Input.plugins.map do |cls|
65
71
  cls.ancestors.include?(Singleton) ? cls.instance : cls.new
@@ -71,6 +77,7 @@ module Fusuma
71
77
  @executors = Plugin::Executors::Executor.plugins.map(&:new)
72
78
  end
73
79
 
80
+ #: () -> void
74
81
  def run
75
82
  loop { pipeline }
76
83
  end
@@ -193,6 +200,7 @@ module Fusuma
193
200
  @buffers.each(&:clear_expired)
194
201
  end
195
202
 
203
+ #: () -> void
196
204
  def set_trap
197
205
  Signal.trap("INT") {
198
206
  shutdown
@@ -206,6 +214,7 @@ module Fusuma
206
214
 
207
215
  private
208
216
 
217
+ #: () -> Array[untyped]
209
218
  def shutdown
210
219
  [@inputs, @filters, @parsers, @buffers, @detectors, @executors].flatten.compact.each do |plugin|
211
220
  plugin.shutdown
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: 3.9.0
4
+ version: 3.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - iberianpig
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-05-26 00:00:00.000000000 Z
11
+ date: 2025-10-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