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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 25a6fc321e7305354cb3b86d331dd4ec749043eaeef977dc125efbd0a515533f
4
- data.tar.gz: 5621071b0f8cf1997dbed8a4cd25afbe7cd9721ee6d9ec0178c201d2fcd20f37
3
+ metadata.gz: 7161de044b786ed9f12f64be26a497307ba1ea87159760e68b5ac90d87ea1d73
4
+ data.tar.gz: aa9359be7d9c0bcc6ca283ba5c2aa17b55f07424a26d3f22b056c47b924488bc
5
5
  SHA512:
6
- metadata.gz: adc8d6c912cb7e650ed51e7c28a021e58a3be91a61190458e7e25bc7450051b01cbc10876c882fde11e70c60575c64163f547dbb6932e5c4a6682792fb995375
7
- data.tar.gz: 2796ede1b96046738a3e1feb93f0137a7f4b48fd599752b9b4d6ab047f9ffdcf082f2aaf94ef4988f3cafde150e89522db057222804acdaf8d2f80593ed0d543
6
+ metadata.gz: 1187109a3b4b3ba67b35feaa274ab73a58dc3411ae8b3de6f62e5ef153c7ca8647383ae0cebeeb8e5632bd69ec0218477826e5e5aa4d32002233a87b521eba43
7
+ data.tar.gz: eec0e66de8f07b7e64ffec123b16a1b51103701346819b0b048850d83e8bf8a78c020f3d51e889f7ff5474218d534a7e7e6bf834bac36c6ff739f279a06da4c8
data/README.md CHANGED
@@ -9,7 +9,7 @@ Fusuma is a powerful tool designed to enable multitouch gesture recognition on L
9
9
 
10
10
  ## Features
11
11
 
12
- - **Easy Installation**: Quick setup via RubyGems.
12
+ - **Easy Installation**: Quick generate via RubyGems.
13
13
  - **Flexible Configuration**: Customize gestures and actions freely in YAML file format.
14
14
  - **Sensitivity Settings**: Fine-tune gesture recognition with adjustable thresholds and intervals to suit your preferences and enhance precision.
15
15
  - **Extension through Plugins**: A [plugin system](https://github.com/iberianpig/fusuma/#fusuma-plugins) allows for additional functionality as needed.
@@ -449,6 +449,32 @@ I'm a Freelance Engineer in Japan and working on these products after finishing
449
449
  Currently, my open-source contribution times is not enough.
450
450
  If you like my work and want to contribute and become a sponsor, I will be able to focus on my projects.
451
451
 
452
+ ## Development
453
+
454
+ ### Type Checking
455
+
456
+ Fusuma uses [RBS](https://github.com/ruby/rbs) for type signatures and [Steep](https://github.com/soutaro/steep) for type checking.
457
+
458
+ #### Running Type Checks
459
+
460
+ ```sh
461
+ # Generate RBS signatures and run type checking
462
+ bundle exec rake rbs:generate && bundle exec steep check
463
+
464
+ # Validate RBS files
465
+ bundle exec rake rbs:validate
466
+
467
+ # Generate inline RBS from code comments
468
+ bundle exec rbs-inline --opt-out lib --output --base .
469
+ ```
470
+
471
+ #### RBS Development
472
+
473
+ The project uses both traditional RBS files and inline RBS comments:
474
+ - Inline RBS comments in source code (processed by `rbs-inline`)
475
+ - Generated RBS files in `sig/generated/`
476
+ - Type checking via Steep with configuration in `Steepfile`
477
+
452
478
  ## Contributing
453
479
 
454
480
  Bug reports and pull requests are welcome on GitHub at https://github.com/iberianpig/fusuma. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
@@ -5,6 +5,7 @@ module Fusuma
5
5
  class Config
6
6
  # index for config.yml
7
7
  class Index
8
+ #: (Array[untyped] | String | Symbol | Integer) -> void
8
9
  def initialize(keys)
9
10
  case keys
10
11
  when Array
@@ -21,6 +22,9 @@ module Fusuma
21
22
  end
22
23
  end
23
24
 
25
+ attr_reader :keys #: Array[Key]
26
+ attr_reader :cache_key #: Symbol | Integer
27
+
24
28
  def to_s
25
29
  @keys.map(&:inspect)
26
30
  end
@@ -31,15 +35,18 @@ module Fusuma
31
35
  cache_key == other.cache_key
32
36
  end
33
37
 
34
- attr_reader :keys, :cache_key
35
-
36
38
  # Keys in Index
37
39
  class Key
40
+ attr_reader :symbol #: Symbol | Integer
41
+ attr_reader :skippable #: bool
42
+
43
+ #: (String | Integer | Symbol, ?skippable: bool) -> void
38
44
  def initialize(symbol_word, skippable: false)
39
- @symbol = begin
40
- symbol_word.to_sym
41
- rescue
45
+ @symbol = case symbol_word
46
+ when Integer, Symbol
42
47
  symbol_word
48
+ else
49
+ symbol_word.to_sym
43
50
  end
44
51
 
45
52
  @skippable = skippable
@@ -52,8 +59,6 @@ module Fusuma
52
59
  @symbol.to_s
53
60
  end
54
61
  end
55
-
56
- attr_reader :symbol, :skippable
57
62
  end
58
63
  end
59
64
  end
@@ -5,6 +5,7 @@ module Fusuma
5
5
  class Config
6
6
  # Search config.yml
7
7
  class Searcher
8
+ #: () -> void
8
9
  def initialize
9
10
  @cache = {}
10
11
  end
@@ -14,6 +15,7 @@ module Fusuma
14
15
  # @return [NilClass]
15
16
  # @return [Hash]
16
17
  # @return [Object]
18
+ #: (Fusuma::Config::Index, location: untyped) -> untyped
17
19
  def search(index, location:)
18
20
  key = index.keys.first
19
21
  return location if key.nil?
@@ -22,7 +24,7 @@ module Fusuma
22
24
 
23
25
  return nil unless location.is_a?(Hash)
24
26
 
25
- next_index = Index.new(index.keys[1..-1])
27
+ next_index = Index.new(Array(index.keys[1..-1]))
26
28
 
27
29
  value = nil
28
30
  next_location_cadidates(location, key).find do |next_location|
@@ -31,6 +33,7 @@ module Fusuma
31
33
  value
32
34
  end
33
35
 
36
+ #: (Fusuma::Config::Index, location: Array[untyped], context: Hash[untyped, untyped] | nil) -> untyped
34
37
  def search_with_context(index, location:, context:)
35
38
  return nil if location.nil?
36
39
 
@@ -48,12 +51,14 @@ module Fusuma
48
51
  # @return [NilClass]
49
52
  # @return [Hash]
50
53
  # @return [Object]
54
+ #: (Fusuma::Config::Index, location: Array[untyped])
51
55
  def search_with_cache(index, location:)
52
56
  cache([index.cache_key, Searcher.context]) do
53
57
  search_with_context(index, location: location, context: Searcher.context)
54
58
  end
55
59
  end
56
60
 
61
+ #: (Array[untyped] | String) { () -> untyped } -> untyped
57
62
  def cache(key)
58
63
  key = key.join(",") if key.is_a? Array
59
64
  if @cache.key?(key)
@@ -68,6 +73,7 @@ module Fusuma
68
73
  # next locations' candidates sorted by priority
69
74
  # 1. look up location with key
70
75
  # 2. skip the key and go to child location
76
+ #: (Hash[untyped, untyped], Fusuma::Config::Index::Key) -> Array[untyped]
71
77
  def next_location_cadidates(location, key)
72
78
  [
73
79
  location[key.symbol],
@@ -81,19 +87,20 @@ module Fusuma
81
87
  # Search with context from load_streamed Config
82
88
  # @param context [Hash]
83
89
  # @return [Object]
90
+ #: (?Hash[untyped, untyped]) { () -> untyped } -> untyped
84
91
  def with_context(context = {}, &block)
85
92
  before = @context
86
93
  @context = context
87
- result = block.call
94
+ block.call
88
95
  ensure # NOTE: ensure is called even if return in block
89
96
  @context = before
90
- result
91
97
  end
92
98
 
93
99
  CONTEXT_SEARCH_ORDER = [:no_context, :complete_match_context, :partial_match_context]
94
100
  # Return a matching context from config
95
101
  # @params request_context [Hash]
96
102
  # @return [Hash]
103
+ #: (Hash[untyped, untyped], ?Array[untyped]) { () -> untyped } -> Hash[untyped, untyped]?
97
104
  def find_context(request_context, fallbacks = CONTEXT_SEARCH_ORDER, &block)
98
105
  # Search in blocks in the following order.
99
106
  # 1. primary context(no context)
@@ -113,6 +120,7 @@ module Fusuma
113
120
  # No context(primary context)
114
121
  # @return [Hash]
115
122
  # @return [NilClass]
123
+ #: (Hash[untyped, untyped]) { () -> untyped } -> Hash[untyped, untyped]?
116
124
  def no_context(_request_context, &block)
117
125
  {} if with_context({}, &block)
118
126
  end
@@ -121,6 +129,7 @@ module Fusuma
121
129
  # @param request_context [Hash]
122
130
  # @return [Hash] matched context
123
131
  # @return [NilClass] if not matched
132
+ #: (Hash[untyped, untyped]) { () -> untyped } -> Hash[untyped, untyped]?
124
133
  def complete_match_context(request_context, &block)
125
134
  Config.instance.keymap.each do |config|
126
135
  next unless config[:context] == request_context
@@ -133,6 +142,7 @@ module Fusuma
133
142
  # @param request_context [Hash]
134
143
  # @return [Hash] matched context
135
144
  # @return [NilClass] if not matched
145
+ #: (Hash[untyped, untyped]) { () -> untyped } -> Hash[untyped, untyped]?
136
146
  def partial_match_context(request_context, &block)
137
147
  if request_context.keys.size > 1
138
148
  Config.instance.keymap.each do |config|
@@ -155,6 +165,7 @@ module Fusuma
155
165
  # @param request_context [Hash]
156
166
  # @return [Hash] matched context
157
167
  # @return [NilClass] if not matched
168
+ #: (Hash[untyped, untyped]) { () -> untyped } -> Hash[untyped, untyped]?
158
169
  def plugin_default_context(request_context, &block)
159
170
  complete_match_context = nil
160
171
  Config.instance.keymap.each do |config|
@@ -167,9 +178,9 @@ module Fusuma
167
178
 
168
179
  return config[:context] if with_context(config[:context], &block)
169
180
  end
170
- if complete_match_context
171
- with_context(complete_match_context, &block)
172
- complete_match_context
181
+
182
+ complete_match_context&.tap do |context|
183
+ with_context(context, &block)
173
184
  end
174
185
  end
175
186
  end
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "yaml"
4
+
3
5
  module Fusuma
4
6
  class Config
5
7
  # ref: https://github.com/rubocop-hq/rubocop/blob/97e4ffc8a71e9e5239a927c6a534dfc1e0da917f/lib/rubocop/yaml_duplication_checker.rb
6
8
  # Find duplicated keys from YAML.
9
+ # steep:ignore:start
7
10
  module YAMLDuplicationChecker
11
+ #: (String, String) { (string) -> void } -> void
8
12
  def self.check(yaml_string, filename, &on_duplicated)
9
13
  tree = YAML.parse(yaml_string, filename: filename)
10
14
  return unless tree
@@ -12,6 +16,7 @@ module Fusuma
12
16
  traverse(tree, &on_duplicated)
13
17
  end
14
18
 
19
+ #: (untyped) { () -> void } -> Array[untyped]?
15
20
  def self.traverse(tree, &on_duplicated)
16
21
  case tree
17
22
  when Psych::Nodes::Mapping
@@ -31,5 +36,6 @@ module Fusuma
31
36
 
32
37
  private_class_method :traverse
33
38
  end
39
+ # steep:ignore:end
34
40
  end
35
41
  end
data/lib/fusuma/config.rb CHANGED
@@ -20,6 +20,7 @@ module Fusuma
20
20
  include Singleton
21
21
 
22
22
  class << self
23
+ #: (Fusuma::Config::Index) -> (String | Hash[untyped, untyped] | Integer | Float)?
23
24
  def search(index)
24
25
  instance.search(index)
25
26
  end
@@ -28,6 +29,7 @@ module Fusuma
28
29
  instance.find_execute_key(index)
29
30
  end
30
31
 
32
+ #: (String?) -> Fusuma::Config
31
33
  def custom_path=(new_path)
32
34
  instance.custom_path = new_path
33
35
  end
@@ -35,22 +37,26 @@ module Fusuma
35
37
 
36
38
  attr_reader :custom_path, :searcher
37
39
 
40
+ #: () -> void
38
41
  def initialize
39
42
  @searcher = Searcher.new
40
43
  @custom_path = nil
41
44
  @keymap = nil
42
45
  end
43
46
 
47
+ #: (String?) -> Fusuma::Config
44
48
  def custom_path=(new_path)
45
49
  @custom_path = new_path
46
50
  reload
47
51
  end
48
52
 
53
+ #: () -> Array[untyped]?
49
54
  def keymap
50
55
  # FIXME: @keymap is not initialized when called from outside Fusuma::Runner like fusuma-senkey
51
56
  @keymap || reload.keymap
52
57
  end
53
58
 
59
+ #: () -> Fusuma::Config
54
60
  def reload
55
61
  plugin_defaults = plugin_defaults_paths.map do |default_yml|
56
62
  {
@@ -76,6 +82,7 @@ module Fusuma
76
82
  # @param key [Symbol]
77
83
  # @param base [Config::Index]
78
84
  # @return [Hash]
85
+ #: (Symbol?, Fusuma::Config::Index) -> (String | Hash[untyped, untyped] | Float | Integer | bool)?
79
86
  def fetch_config_params(key, base)
80
87
  request_context = {plugin_defaults: base.keys.last.symbol.to_s}
81
88
  fallbacks = [:no_context, :plugin_default_context]
@@ -90,15 +97,16 @@ module Fusuma
90
97
 
91
98
  # @return [Hash] If check passes
92
99
  # @raise [InvalidFileError] If check does not pass
100
+ #: (String) -> Array[Hash[Symbol, untyped]]
93
101
  def validate(path)
94
102
  duplicates = []
95
- YAMLDuplicationChecker.check(File.read(path), path) do |ignored, duplicate|
103
+ YAMLDuplicationChecker.check(File.read(path), path) do |ignored, duplicate| # steep:ignore UnexpectedBlockGiven
96
104
  MultiLogger.error "#{path}: #{ignored.value} is duplicated"
97
105
  duplicates << duplicate.value
98
106
  end
99
107
  raise InvalidFileError, "Detect duplicate keys #{duplicates}" unless duplicates.empty?
100
108
 
101
- yamls = YAML.load_stream(File.read(path)).compact
109
+ yamls = YAML.load_stream(File.read(path)).compact # steep:ignore NoMethod
102
110
  yamls.map do |yaml|
103
111
  raise InvalidFileError, "Invalid config.yml: #{path}" unless yaml.is_a? Hash
104
112
 
@@ -109,7 +117,9 @@ module Fusuma
109
117
  end
110
118
 
111
119
  # @param index [Index]
120
+ #: (Fusuma::Config::Index) -> (String | Hash[untyped, untyped] | Integer | Float)?
112
121
  def search(index)
122
+ return nil if index.nil? || index.keys.empty?
113
123
  @searcher.search_with_cache(index, location: keymap)
114
124
  end
115
125
 
@@ -120,7 +130,7 @@ module Fusuma
120
130
  executor.new.execute_keys
121
131
  end.flatten
122
132
 
123
- @cache_execute_keys ||= {}
133
+ @cache_execute_keys ||= {} #: Hash[String, untyped]
124
134
 
125
135
  cache_key = [index.cache_key, Searcher.context].join
126
136
 
@@ -135,6 +145,7 @@ module Fusuma
135
145
 
136
146
  private
137
147
 
148
+ #: () -> String
138
149
  def find_config_filepath
139
150
  filename = "fusuma/config.yml"
140
151
  if custom_path
@@ -149,10 +160,12 @@ module Fusuma
149
160
  end
150
161
  end
151
162
 
163
+ #: () -> String
152
164
  def expand_custom_path
153
165
  File.expand_path(custom_path)
154
166
  end
155
167
 
168
+ #: (String) -> String
156
169
  def expand_config_path(filename)
157
170
  File.expand_path "~/.config/#{filename}"
158
171
  end
@@ -161,6 +174,7 @@ module Fusuma
161
174
  File.expand_path "../../#{filename}", __FILE__
162
175
  end
163
176
 
177
+ #: () -> Array[untyped]
164
178
  def plugin_defaults_paths
165
179
  Plugin::Manager.load_paths.map do |plugin_path|
166
180
  yml = plugin_path.gsub(/\.rb$/, ".yml")
@@ -7,10 +7,12 @@ module Fusuma
7
7
  module CustomProcess
8
8
  attr_writer :proctitle
9
9
 
10
+ #: () -> Array[untyped]
10
11
  def child_pids
11
12
  @child_pids ||= []
12
13
  end
13
14
 
15
+ #: () { () -> void } -> nil
14
16
  def fork
15
17
  pid = Process.fork do
16
18
  Process.setproctitle(proctitle)
@@ -35,6 +37,7 @@ module Fusuma
35
37
  end
36
38
  end
37
39
 
40
+ #: () -> String
38
41
  def proctitle
39
42
  @proctitle ||= self.class.name.underscore
40
43
  end
data/lib/fusuma/device.rb CHANGED
@@ -8,6 +8,7 @@ module Fusuma
8
8
  class Device
9
9
  attr_reader :id, :name, :capabilities, :available
10
10
 
11
+ #: (?id: nil | String, ?name: nil | String, ?capabilities: nil, ?available: nil | bool) -> void
11
12
  def initialize(id: nil, name: nil, capabilities: nil, available: nil)
12
13
  @id = id
13
14
  @name = name
@@ -16,6 +17,7 @@ module Fusuma
16
17
  end
17
18
 
18
19
  # @param attributes [Hash]
20
+ #: (Hash[untyped, untyped]) -> Hash[untyped, untyped]
19
21
  def assign_attributes(attributes)
20
22
  attributes.each do |k, v|
21
23
  case k
@@ -35,6 +37,7 @@ module Fusuma
35
37
  # Return devices
36
38
  # sort devices by capabilities of gesture
37
39
  # @return [Array]
40
+ #: () -> Array[Device]
38
41
  def all
39
42
  @all ||= fetch_devices.partition do |d|
40
43
  d.capabilities.match?(/gesture/)
@@ -43,6 +46,7 @@ module Fusuma
43
46
 
44
47
  # @raise [SystemExit]
45
48
  # @return [Array]
49
+ #: () -> Array[Device]
46
50
  def available
47
51
  @available ||= all.select(&:available).tap do |d|
48
52
  MultiLogger.debug(available_devices: d)
@@ -54,6 +58,7 @@ module Fusuma
54
58
  exit 1
55
59
  end
56
60
 
61
+ #: () -> nil
57
62
  def reset
58
63
  @all = nil
59
64
  @available = nil
@@ -62,6 +67,7 @@ module Fusuma
62
67
  private
63
68
 
64
69
  # @return [Array]
70
+ #: () -> Array[Device]
65
71
  def fetch_devices
66
72
  line_parser = LineParser.new
67
73
 
@@ -72,6 +78,7 @@ module Fusuma
72
78
  line_parser.generate_devices
73
79
  end
74
80
 
81
+ #: () -> Fusuma::LibinputCommand
75
82
  def libinput_command
76
83
  @libinput_command ||= Plugin::Inputs::LibinputCommandInput.new.command
77
84
  end
@@ -81,16 +88,19 @@ module Fusuma
81
88
  class LineParser
82
89
  attr_reader :lines
83
90
 
91
+ #: () -> void
84
92
  def initialize
85
93
  @lines = []
86
94
  end
87
95
 
88
96
  # @param line [String]
97
+ #: (String) -> Array[untyped]
89
98
  def push(line)
90
99
  lines.push(line)
91
100
  end
92
101
 
93
102
  # @return [Array]
103
+ #: () -> Array[Device]
94
104
  def generate_devices
95
105
  lines.each_with_object([]) do |line, devices|
96
106
  attributes = extract_attribute(line: line)
@@ -108,6 +118,7 @@ module Fusuma
108
118
 
109
119
  # @param line [String]
110
120
  # @return [Hash]
121
+ #: (line: String) -> Hash[untyped, untyped]
111
122
  def extract_attribute(line:)
112
123
  if (id = id_from(line))
113
124
  {id: id}
@@ -122,24 +133,28 @@ module Fusuma
122
133
  end
123
134
  end
124
135
 
136
+ #: (String) -> String?
125
137
  def id_from(line)
126
138
  line.match("^Kernel:[[:space:]]*") do |m|
127
139
  m.post_match.match(/event[0-9]+/).to_s
128
140
  end
129
141
  end
130
142
 
143
+ #: (String) -> String?
131
144
  def name_from(line)
132
145
  line.match("^Device:[[:space:]]*") do |m|
133
146
  m.post_match.strip
134
147
  end
135
148
  end
136
149
 
150
+ #: (String) -> String?
137
151
  def capabilities_from(line)
138
152
  line.match("^Capabilities:[[:space:]]*") do |m|
139
153
  m.post_match.strip
140
154
  end
141
155
  end
142
156
 
157
+ #: (String) -> bool?
143
158
  def available_from(line)
144
159
  # NOTE: is natural scroll available?
145
160
  if /^Nat.scrolling: /.match?(line)
@@ -8,6 +8,7 @@ module Fusuma
8
8
  # Output Environment information
9
9
  class Environment
10
10
  class << self
11
+ #: () -> void
11
12
  def dump_information
12
13
  MultiLogger.info "---------------------------------------------"
13
14
  print_version
@@ -16,6 +17,7 @@ module Fusuma
16
17
  MultiLogger.info "---------------------------------------------"
17
18
  end
18
19
 
20
+ #: () -> void
19
21
  def print_version
20
22
  libinput_command = Plugin::Inputs::LibinputCommandInput.new.command
21
23
  MultiLogger.info "Fusuma: #{VERSION}"
@@ -26,6 +28,7 @@ module Fusuma
26
28
  MultiLogger.info "Desktop session: #{`echo $DESKTOP_SESSION $XDG_SESSION_TYPE`}".strip
27
29
  end
28
30
 
31
+ #: () -> void
29
32
  def print_enabled_plugins
30
33
  MultiLogger.info "Enabled Plugins: "
31
34
  Plugin::Manager.plugins
@@ -34,6 +37,7 @@ module Fusuma
34
37
  .flatten.sort.each { |name| MultiLogger.info(name) }
35
38
  end
36
39
 
40
+ #: () -> void
37
41
  def print_device_list
38
42
  Plugin::Filters::LibinputDeviceFilter.new.keep_device.all.map do |device|
39
43
  puts device.name
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Patch to hash
3
+ # @rbs generic unchecked out K
4
+ # @rbs generic unchecked out V
4
5
  class Hash
5
6
  # activesupport-5.2.0/lib/active_support/core_ext/hash/deep_merge.rb
6
7
  def deep_merge(other_hash, &block)
@@ -25,6 +26,7 @@ class Hash
25
26
  end
26
27
 
27
28
  # activesupport-4.1.1/lib/active_support/core_ext/hash/keys.rb
29
+ #: () -> Hash[Symbol, untyped]
28
30
  def deep_symbolize_keys
29
31
  deep_transform_keys do |key|
30
32
  key.to_sym
@@ -33,6 +35,7 @@ class Hash
33
35
  end
34
36
  end
35
37
 
38
+ #: [T] () { (untyped) -> T } -> Hash[T, untyped]
36
39
  def deep_transform_keys(&block)
37
40
  result = {}
38
41
  each do |key, value|
@@ -42,6 +45,7 @@ class Hash
42
45
  end
43
46
 
44
47
  # activesupport/lib/active_support/core_ext/hash/deep_transform_values.rb
48
+ #: () { (untyped) -> untyped } -> Hash[untyped, untyped]
45
49
  def deep_transform_values(&block)
46
50
  _deep_transform_values_in_object(self, &block)
47
51
  end
@@ -49,6 +53,7 @@ class Hash
49
53
  private
50
54
 
51
55
  # Support methods for deep transforming nested hashes and arrays.
56
+ #: (Hash[untyped, untyped]) { (untyped) -> untyped } -> Hash[untyped, untyped]
52
57
  def _deep_transform_values_in_object(object, &block)
53
58
  case object
54
59
  when Hash
@@ -5,6 +5,7 @@ require "open3"
5
5
  module Fusuma
6
6
  # Execute libinput command
7
7
  class LibinputCommand
8
+ #: (?libinput_options: Array[String], ?commands: Hash[untyped, untyped]) -> void
8
9
  def initialize(libinput_options: [], commands: {})
9
10
  @libinput_command = commands[:libinput_command]
10
11
  @debug_events_command = commands[:debug_events_command]
@@ -17,6 +18,7 @@ module Fusuma
17
18
  NEW_CLI_OPTION_VERSION = "1.8"
18
19
 
19
20
  # @return [Boolean]
21
+ #: () -> bool
20
22
  def new_cli_option_available?
21
23
  Gem::Version.new(version) >= Gem::Version.new(NEW_CLI_OPTION_VERSION)
22
24
  end
@@ -27,32 +29,35 @@ module Fusuma
27
29
  end
28
30
 
29
31
  # @return [String]
32
+ #: () -> String?
30
33
  def version
31
34
  # version_command prints "1.6.3\n"
32
35
  @version ||= `#{version_command}`.strip
33
36
  end
34
37
 
35
38
  # @yieldparam [String] gives a line in libinput list-devices output to the block
39
+ #: () { (String) -> void } -> void
36
40
  def list_devices(&block)
37
41
  cmd = list_devices_command
38
42
  MultiLogger.debug(list_devices: cmd)
39
- o, e, s = Open3.capture3(cmd)
43
+ o, _, s = Open3.capture3(cmd)
40
44
 
41
45
  unless s.success?
42
- MultiLogger.error("libinput list-devices failed with output: #{o}")
43
- return
46
+ raise "libinput list-devices failed with output: #{o}"
44
47
  end
45
48
 
46
49
  o.each_line(&block)
47
50
  end
48
51
 
49
52
  # @return [Integer] return a latest line libinput debug-events
53
+ #: (StringIO) -> Array[untyped]
50
54
  def debug_events(writer)
51
55
  Open3.pipeline_start([debug_events_with_options], ["grep -v POINTER_ --line-buffered"], out: writer, in: "/dev/null")
52
56
  end
53
57
 
54
58
  # @return [String] command
55
59
  # @raise [SystemExit]
60
+ #: () -> String?
56
61
  def version_command
57
62
  if @libinput_command
58
63
  "#{@libinput_command} --version"
@@ -68,6 +73,7 @@ module Fusuma
68
73
  end
69
74
  end
70
75
 
76
+ #: () -> String
71
77
  def list_devices_command
72
78
  if @libinput_command
73
79
  @libinput_command + " list-devices"
@@ -80,6 +86,7 @@ module Fusuma
80
86
  end
81
87
  end
82
88
 
89
+ #: () -> String
83
90
  def debug_events_command
84
91
  if @libinput_command
85
92
  @libinput_command + " debug-events"
@@ -92,6 +99,7 @@ module Fusuma
92
99
  end
93
100
  end
94
101
 
102
+ #: () -> String
95
103
  def debug_events_with_options
96
104
  prefix = "stdbuf -oL --"
97
105
  "#{prefix} #{debug_events_command} #{@libinput_options.join(" ")}".strip