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.
- checksums.yaml +4 -4
 - data/README.md +27 -1
 - data/lib/fusuma/config/index.rb +12 -7
 - data/lib/fusuma/config/searcher.rb +17 -6
 - data/lib/fusuma/config/yaml_duplication_checker.rb +6 -0
 - data/lib/fusuma/config.rb +17 -3
 - data/lib/fusuma/custom_process.rb +3 -0
 - data/lib/fusuma/device.rb +15 -0
 - data/lib/fusuma/environment.rb +4 -0
 - data/lib/fusuma/hash_support.rb +6 -1
 - data/lib/fusuma/libinput_command.rb +11 -3
 - data/lib/fusuma/multi_logger.rb +15 -4
 - data/lib/fusuma/plugin/base.rb +11 -1
 - data/lib/fusuma/plugin/buffers/buffer.rb +6 -0
 - data/lib/fusuma/plugin/buffers/gesture_buffer.rb +15 -9
 - data/lib/fusuma/plugin/buffers/timer_buffer.rb +2 -1
 - data/lib/fusuma/plugin/detectors/detector.rb +15 -15
 - data/lib/fusuma/plugin/detectors/hold_detector.rb +10 -2
 - data/lib/fusuma/plugin/detectors/pinch_detector.rb +13 -1
 - data/lib/fusuma/plugin/detectors/rotate_detector.rb +11 -0
 - data/lib/fusuma/plugin/detectors/swipe_detector.rb +12 -0
 - data/lib/fusuma/plugin/events/event.rb +5 -2
 - data/lib/fusuma/plugin/events/records/gesture_record.rb +2 -0
 - data/lib/fusuma/plugin/events/records/index_record.rb +2 -0
 - data/lib/fusuma/plugin/events/records/record.rb +1 -0
 - data/lib/fusuma/plugin/events/records/text_record.rb +3 -0
 - data/lib/fusuma/plugin/executors/command_executor.rb +5 -1
 - data/lib/fusuma/plugin/executors/executor.rb +6 -0
 - data/lib/fusuma/plugin/filters/filter.rb +2 -0
 - data/lib/fusuma/plugin/filters/libinput_device_filter.rb +10 -0
 - data/lib/fusuma/plugin/inputs/input.rb +5 -0
 - data/lib/fusuma/plugin/inputs/libinput_command_input.rb +10 -3
 - data/lib/fusuma/plugin/inputs/timer_input.rb +4 -0
 - data/lib/fusuma/plugin/manager.rb +11 -1
 - data/lib/fusuma/plugin/parsers/libinput_gesture_parser.rb +9 -0
 - data/lib/fusuma/plugin/parsers/parser.rb +4 -0
 - data/lib/fusuma/string_support.rb +1 -0
 - data/lib/fusuma/version.rb +1 -1
 - data/lib/fusuma.rb +10 -1
 - 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 
     | 
| 
      
 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
         
     | 
| 
         @@ -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} 
     | 
| 
      
 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 
     | 
    
         
            -
                     
     | 
| 
      
 68 
     | 
    
         
            +
                    #: () -> String?
         
     | 
| 
      
 69 
     | 
    
         
            +
                    def libinput_command # steep:ignore MethodBodyTypeMismatch
         
     | 
| 
       65 
70 
     | 
    
         
             
                      config_params(:"libinput-command")
         
     | 
| 
       66 
71 
     | 
    
         
             
                    end
         
     | 
| 
       67 
72 
     | 
    
         | 
| 
       68 
     | 
    
         
            -
                     
     | 
| 
      
 73 
     | 
    
         
            +
                    #: () -> String?
         
     | 
| 
      
 74 
     | 
    
         
            +
                    def debug_events_command # steep:ignore MethodBodyTypeMismatch
         
     | 
| 
       69 
75 
     | 
    
         
             
                      config_params(:"libinput-debug-events")
         
     | 
| 
       70 
76 
     | 
    
         
             
                    end
         
     | 
| 
       71 
77 
     | 
    
         | 
| 
       72 
     | 
    
         
            -
                     
     | 
| 
      
 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
         
     | 
    
        data/lib/fusuma/version.rb
    CHANGED
    
    
    
        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 
     | 
    
         
            -
                 
     | 
| 
      
 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. 
     | 
| 
      
 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- 
     | 
| 
      
 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
         
     |