fusuma 2.5.1 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +55 -34
- data/exe/fusuma +4 -0
- data/fusuma.gemspec +3 -2
- data/lib/fusuma/config/index.rb +19 -46
- data/lib/fusuma/config/searcher.rb +68 -60
- data/lib/fusuma/config.rb +43 -6
- data/lib/fusuma/custom_process.rb +34 -2
- data/lib/fusuma/device.rb +1 -0
- data/lib/fusuma/environment.rb +6 -0
- data/lib/fusuma/hash_support.rb +22 -0
- data/lib/fusuma/multi_logger.rb +16 -0
- data/lib/fusuma/plugin/base.rb +16 -7
- data/lib/fusuma/plugin/buffers/gesture_buffer.rb +62 -6
- data/lib/fusuma/plugin/detectors/detector.rb +10 -9
- data/lib/fusuma/plugin/detectors/hold_detector.rb +28 -14
- data/lib/fusuma/plugin/detectors/pinch_detector.rb +10 -10
- data/lib/fusuma/plugin/detectors/rotate_detector.rb +4 -11
- data/lib/fusuma/plugin/detectors/swipe_detector.rb +8 -16
- data/lib/fusuma/plugin/events/records/gesture_record.rb +5 -2
- data/lib/fusuma/plugin/events/records/index_record.rb +1 -1
- data/lib/fusuma/plugin/executors/command_executor.rb +2 -2
- data/lib/fusuma/plugin/executors/executor.rb +1 -4
- data/lib/fusuma/plugin/filters/libinput_device_filter.rb +2 -1
- data/lib/fusuma/plugin/inputs/input.rb +14 -36
- data/lib/fusuma/plugin/inputs/libinput_command_input.yml +3 -0
- data/lib/fusuma/plugin/inputs/timer_input.rb +36 -21
- data/lib/fusuma/plugin/manager.rb +17 -6
- data/lib/fusuma/version.rb +1 -1
- data/lib/fusuma.rb +51 -36
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ff7ea9fcd08ba0c48e1c08d9eceeb4a1e30684a0616f37fef6f67a3e035c005
|
4
|
+
data.tar.gz: c68adc10a8e2b7fb5396c7c789f941b13bacc9d60d6d669a7d8004c773503d75
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46fdbcb0b697ba9000e55de86a9550d783c81c6407f13ebe82375c2b741341a591bcf45fe6c707247a9a2017e4f3ca4834111af551a4a65001cc7e944487b28e
|
7
|
+
data.tar.gz: e0e579b0d73ea237202ae17f641c07a1ed7587a771c71bfe12d55edec62b3d9e3281fd010f646e6e7077a6245e0365d0ed73c7042528a8c8c5ac72bbeed956de
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
# Fusuma
|
1
|
+
# Fusuma
|
2
|
+
![Gem](https://img.shields.io/gem/v/fusuma?color=brightgreen) [![Build Status](https://github.com/iberianpig/fusuma/actions/workflows/main.yml/badge.svg)](https://github.com/iberianpig/fusuma/actions/workflows/main.yml)
|
2
3
|
|
3
4
|
Fusuma is multitouch gesture recognizer.
|
4
5
|
This gem makes your linux able to recognize swipes or pinchs and assign commands to them.
|
@@ -21,23 +22,28 @@ This gem makes your linux able to recognize swipes or pinchs and assign commands
|
|
21
22
|
|
22
23
|
**IMPORTANT**: You **MUST** be a member of the **INPUT** group to read touchpad by Fusuma.
|
23
24
|
|
24
|
-
```
|
25
|
+
```sh
|
25
26
|
sudo gpasswd -a $USER input
|
26
27
|
```
|
27
28
|
|
28
29
|
Then, You apply the change with no logout or reboot.
|
29
30
|
|
30
|
-
```
|
31
|
+
```sh
|
31
32
|
newgrp input
|
32
33
|
```
|
33
34
|
|
35
|
+
**IMPORTANT**: This makes `/dev/input/` readable, so if that's an issue for you for some reason (like for privacy- or securityconcerns etc. or if it causes other parts of your OS to misbehave), **consider this your heads-up.**
|
36
|
+
|
37
|
+
<details>
|
38
|
+
<summary>For Debian Based Distros (Ubuntu, Debian, Mint, Pop!OS)</summary>
|
39
|
+
|
34
40
|
### For Debian Based Distros (Ubuntu, Debian, Mint, Pop!OS)
|
35
41
|
|
36
42
|
#### 1. Install libinput-tools
|
37
43
|
|
38
44
|
You need `libinput` release 1.0 or later.
|
39
45
|
|
40
|
-
```
|
46
|
+
```sh
|
41
47
|
sudo apt-get install libinput-tools
|
42
48
|
```
|
43
49
|
|
@@ -45,13 +51,13 @@ sudo apt-get install libinput-tools
|
|
45
51
|
|
46
52
|
Fusuma runs in Ruby, so you must install it first.
|
47
53
|
|
48
|
-
```
|
54
|
+
```sh
|
49
55
|
sudo apt-get install ruby
|
50
56
|
```
|
51
57
|
|
52
58
|
#### 3. Install Fusuma
|
53
59
|
|
54
|
-
```
|
60
|
+
```sh
|
55
61
|
sudo gem install fusuma
|
56
62
|
```
|
57
63
|
|
@@ -59,26 +65,31 @@ sudo gem install fusuma
|
|
59
65
|
|
60
66
|
For sending shortcuts:
|
61
67
|
|
62
|
-
```
|
68
|
+
```sh
|
63
69
|
sudo apt-get install xdotool
|
64
70
|
```
|
65
71
|
|
72
|
+
</details>
|
73
|
+
|
74
|
+
<details>
|
75
|
+
<summary> For Arch Based Distros (Manjaro, Arch) </summary>
|
76
|
+
|
66
77
|
### For Arch Based Distros (Manjaro, Arch)
|
67
78
|
|
68
79
|
#### 1. Install libinput.
|
69
80
|
|
70
81
|
You need `libinput` release 1.0 or later. This is most probably installed by default on Manjaro
|
71
82
|
|
72
|
-
```
|
73
|
-
sudo pacman -
|
83
|
+
```sh
|
84
|
+
sudo pacman -Syu libinput
|
74
85
|
```
|
75
86
|
|
76
87
|
#### 2. Install Ruby
|
77
88
|
|
78
89
|
Fusuma runs in Ruby, so you must install it first.
|
79
90
|
|
80
|
-
```
|
81
|
-
sudo pacman -
|
91
|
+
```sh
|
92
|
+
sudo pacman -Syu ruby
|
82
93
|
```
|
83
94
|
|
84
95
|
#### 3. Install Fusuma
|
@@ -87,7 +98,7 @@ sudo pacman -S ruby
|
|
87
98
|
|
88
99
|
To install gems system-wide, see any of the methods listed on [Arch Wiki](https://wiki.archlinux.org/index.php/ruby#Installing_gems_system-wide)
|
89
100
|
|
90
|
-
```
|
101
|
+
```sh
|
91
102
|
sudo gem install fusuma
|
92
103
|
```
|
93
104
|
|
@@ -95,9 +106,19 @@ sudo gem install fusuma
|
|
95
106
|
|
96
107
|
For sending shortcuts:
|
97
108
|
|
98
|
-
```
|
99
|
-
sudo pacman -
|
109
|
+
```sh
|
110
|
+
sudo pacman -Syu xdotool
|
100
111
|
```
|
112
|
+
**For the truly lazy people:** As with pretty much anything else available as Open-Source-Software, you can install Fusuma via a package from the AUR. As off time of writing (March 2023), the package you would want is called `ruby-fusuma`.
|
113
|
+
|
114
|
+
Please keep in mind that this community-built package is NOT officially supported here and while it might do the job, it is not the intended way to install.
|
115
|
+
Installing Fusuma this way means that if things do not work as intended during or after the installation, you are on your own.
|
116
|
+
So please do not bombard the Issues-Page here on Github if Fusuma isn't working correctly after installing it via the AUR.
|
117
|
+
Fusuma's plugins as listed below here in this Readme can be installed as optional dependencies also via the AUR, namescheme being `ruby-fusuma-replacewithnameofplugin`.
|
118
|
+
</details>
|
119
|
+
|
120
|
+
<details>
|
121
|
+
<summary>For Fedora</summary>
|
101
122
|
|
102
123
|
### For Fedora
|
103
124
|
|
@@ -105,7 +126,7 @@ sudo pacman -S xdotool
|
|
105
126
|
|
106
127
|
You need `libinput` release 1.0 or later.
|
107
128
|
|
108
|
-
```
|
129
|
+
```sh
|
109
130
|
sudo dnf install libinput
|
110
131
|
```
|
111
132
|
|
@@ -113,13 +134,13 @@ sudo dnf install libinput
|
|
113
134
|
|
114
135
|
Fusuma runs in Ruby, so you must install it first.
|
115
136
|
|
116
|
-
```
|
137
|
+
```sh
|
117
138
|
sudo dnf install ruby
|
118
139
|
```
|
119
140
|
|
120
141
|
#### 3. Install Fusuma
|
121
142
|
|
122
|
-
```
|
143
|
+
```sh
|
123
144
|
sudo gem install fusuma
|
124
145
|
```
|
125
146
|
|
@@ -127,27 +148,28 @@ sudo gem install fusuma
|
|
127
148
|
|
128
149
|
For sending shortcuts:
|
129
150
|
|
130
|
-
```
|
151
|
+
```sh
|
131
152
|
sudo dnf install xdotool
|
132
153
|
```
|
154
|
+
</details>
|
133
155
|
|
134
156
|
### Touchpad not working in GNOME
|
135
157
|
|
136
158
|
Ensure the touchpad events are being sent to the GNOME desktop by running the following command:
|
137
159
|
|
138
|
-
```
|
160
|
+
```sh
|
139
161
|
gsettings set org.gnome.desktop.peripherals.touchpad send-events enabled
|
140
162
|
```
|
141
163
|
|
142
164
|
## Usage
|
143
165
|
|
144
|
-
```
|
166
|
+
```sh
|
145
167
|
fusuma
|
146
168
|
```
|
147
169
|
|
148
170
|
## Update
|
149
171
|
|
150
|
-
```
|
172
|
+
```sh
|
151
173
|
sudo gem update fusuma
|
152
174
|
```
|
153
175
|
|
@@ -156,7 +178,7 @@ sudo gem update fusuma
|
|
156
178
|
You can customize the settings for gestures to put and edit `~/.config/fusuma/config.yml`.
|
157
179
|
**NOTE: You will need to create the `~/.config/fusuma` directory if it doesn't exist yet.**
|
158
180
|
|
159
|
-
```
|
181
|
+
```sh
|
160
182
|
mkdir -p ~/.config/fusuma # create config directory
|
161
183
|
nano ~/.config/fusuma/config.yml # edit config file.
|
162
184
|
```
|
@@ -322,7 +344,6 @@ swipe:
|
|
322
344
|
#### Alternatives to xdotool
|
323
345
|
|
324
346
|
- [fusuma-plugin-sendkey](https://github.com/iberianpig/fusuma-plugin-sendkey)
|
325
|
-
|
326
347
|
- Emulates keyboard events
|
327
348
|
- Low latency
|
328
349
|
- Wayland compatible
|
@@ -334,7 +355,8 @@ swipe:
|
|
334
355
|
- [ydotool](https://github.com/ReimuNotMoe/ydotool)
|
335
356
|
- Wayland compatible
|
336
357
|
- Needs more maintainers.
|
337
|
-
|
358
|
+
|
359
|
+
|
338
360
|
|
339
361
|
## Options
|
340
362
|
|
@@ -376,22 +398,22 @@ Following features are provided as plugins.
|
|
376
398
|
|
377
399
|
Fusuma plugins are provided with the `fusuma-plugin-XXXXX` naming convention and hosted on [RubyGems](https://rubygems.org/search?utf8=%E2%9C%93&query=fusuma-plugins).
|
378
400
|
|
379
|
-
| Name | Version
|
380
|
-
|
|
381
|
-
| [fusuma-plugin-sendkey](https://github.com/iberianpig/fusuma-plugin-sendkey) | ![Gem
|
382
|
-
| [fusuma-plugin-wmctrl](https://github.com/iberianpig/fusuma-plugin-wmctrl) | ![Gem
|
383
|
-
| [fusuma-plugin-keypress](https://github.com/iberianpig/fusuma-plugin-keypress) | ![Gem
|
384
|
-
| [fusuma-plugin-tap](https://github.com/iberianpig/fusuma-plugin-tap) | ![Gem
|
385
|
-
| [fusuma-plugin-appmatcher](https://github.com/iberianpig/fusuma-plugin-appmatcher) | ![Gem
|
401
|
+
| Name | Version | About |
|
402
|
+
| --- | --- | --- |
|
403
|
+
| [fusuma-plugin-sendkey](https://github.com/iberianpig/fusuma-plugin-sendkey) | ![Gem](https://img.shields.io/gem/v/fusuma-plugin-sendkey?color=brightgreen) | Emulates keyboard events(Wayland compatible) |
|
404
|
+
| [fusuma-plugin-wmctrl](https://github.com/iberianpig/fusuma-plugin-wmctrl) | ![Gem](https://img.shields.io/gem/v/fusuma-plugin-wmctrl?color=brightgreen) | Manages Window and Workspace |
|
405
|
+
| [fusuma-plugin-keypress](https://github.com/iberianpig/fusuma-plugin-keypress) | ![Gem](https://img.shields.io/gem/v/fusuma-plugin-keypress?color=brightgreen) | Detecting a combination of key presses and touchpad gestures |
|
406
|
+
| [fusuma-plugin-tap](https://github.com/iberianpig/fusuma-plugin-tap) | ![Gem](https://img.shields.io/gem/v/fusuma-plugin-tap?color=brightgreen) | Detects Tap gesture |
|
407
|
+
| [fusuma-plugin-appmatcher](https://github.com/iberianpig/fusuma-plugin-appmatcher) | ![Gem](https://img.shields.io/gem/v/fusuma-plugin-appmatcher?color=brightgreen) | Configure app-specific gestures |
|
386
408
|
|
387
409
|
|
388
410
|
### Installation of Fusuma plugins
|
389
411
|
|
390
|
-
```
|
412
|
+
```sh
|
391
413
|
# install fusuma-plugin-XXXX
|
392
414
|
sudo gem install fusuma-plugin-XXXXX`
|
393
415
|
```
|
394
|
-
```
|
416
|
+
```sh
|
395
417
|
# update
|
396
418
|
sudo gem list fusuma-plugin- | cut -d' ' -f1 | xargs --no-run-if-empty sudo gem update
|
397
419
|
```
|
@@ -408,7 +430,6 @@ Currently, my open-source contribution times is not enough.
|
|
408
430
|
If you like my work and want to contribute and become a sponsor, I will be able to focus on my projects.
|
409
431
|
|
410
432
|
- [GitHub Sponsors](https://github.com/sponsors/iberianpig)
|
411
|
-
- [Patreon](https://www.patreon.com/iberianpig)
|
412
433
|
|
413
434
|
## Contributing
|
414
435
|
|
data/exe/fusuma
CHANGED
@@ -27,6 +27,10 @@ opt.on('--log=path/to/file',
|
|
27
27
|
option[:log_filepath] = v
|
28
28
|
end
|
29
29
|
|
30
|
+
opt.on('--show-config', 'Show config as YAML format which is loaded internally') do |v|
|
31
|
+
option[:show_config] = v
|
32
|
+
end
|
33
|
+
|
30
34
|
opt.on('--device="Device name"',
|
31
35
|
'Open the given device only (DEPRECATED)') do |v|
|
32
36
|
option[:device] = v
|
data/fusuma.gemspec
CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
"yard.run" => "yri" # use "yard" to build full HTML docs.
|
25
25
|
}
|
26
26
|
|
27
|
-
spec.required_ruby_version = ">= 2.
|
28
|
-
#
|
27
|
+
spec.required_ruby_version = ">= 2.7"
|
28
|
+
# https://packages.ubuntu.com/search?keywords=ruby&searchon=names&exact=1&suite=all§ion=main
|
29
|
+
# support focal (20.04LTS) 2.7
|
29
30
|
end
|
data/lib/fusuma/config/index.rb
CHANGED
@@ -6,17 +6,19 @@ module Fusuma
|
|
6
6
|
# index for config.yml
|
7
7
|
class Index
|
8
8
|
def initialize(keys)
|
9
|
-
@
|
9
|
+
@count = 0
|
10
|
+
case keys
|
10
11
|
when Array
|
11
|
-
keys
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
12
|
+
@keys = []
|
13
|
+
@cache_key = keys.map do |key|
|
14
|
+
key = Key.new(key) if !key.is_a? Key
|
15
|
+
@keys << key
|
16
|
+
key.symbol
|
17
|
+
end.join(",")
|
18
18
|
else
|
19
|
-
|
19
|
+
key = Key.new(keys)
|
20
|
+
@cache_key = key.symbol
|
21
|
+
@keys = [key]
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
@@ -24,36 +26,11 @@ module Fusuma
|
|
24
26
|
@keys.map(&:inspect)
|
25
27
|
end
|
26
28
|
|
27
|
-
attr_reader :keys
|
28
|
-
|
29
|
-
def cache_key
|
30
|
-
case @keys
|
31
|
-
when Array
|
32
|
-
@keys.map(&:symbol).join(",")
|
33
|
-
when Key
|
34
|
-
@keys.symbol
|
35
|
-
else
|
36
|
-
raise "invalid keys"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# @return [Index]
|
41
|
-
def with_context
|
42
|
-
keys = @keys.map do |key|
|
43
|
-
next if Searcher.skip? && key.skippable
|
44
|
-
|
45
|
-
if Searcher.fallback? && key.fallback
|
46
|
-
key.fallback
|
47
|
-
else
|
48
|
-
key
|
49
|
-
end
|
50
|
-
end
|
51
|
-
self.class.new(keys.compact)
|
52
|
-
end
|
29
|
+
attr_reader :keys, :cache_key
|
53
30
|
|
54
31
|
# Keys in Index
|
55
32
|
class Key
|
56
|
-
def initialize(symbol_word, skippable: false
|
33
|
+
def initialize(symbol_word, skippable: false)
|
57
34
|
@symbol = begin
|
58
35
|
symbol_word.to_sym
|
59
36
|
rescue
|
@@ -61,21 +38,17 @@ module Fusuma
|
|
61
38
|
end
|
62
39
|
|
63
40
|
@skippable = skippable
|
64
|
-
|
65
|
-
@fallback = begin
|
66
|
-
fallback.to_sym
|
67
|
-
rescue
|
68
|
-
fallback
|
69
|
-
end
|
70
41
|
end
|
71
42
|
|
72
43
|
def inspect
|
73
|
-
|
74
|
-
|
75
|
-
|
44
|
+
if @skippable
|
45
|
+
"#{@symbol}(skippable)"
|
46
|
+
else
|
47
|
+
@symbol.to_s
|
48
|
+
end
|
76
49
|
end
|
77
50
|
|
78
|
-
attr_reader :symbol, :skippable
|
51
|
+
attr_reader :symbol, :skippable
|
79
52
|
end
|
80
53
|
end
|
81
54
|
end
|
@@ -6,7 +6,7 @@ module Fusuma
|
|
6
6
|
# Search config.yml
|
7
7
|
class Searcher
|
8
8
|
def initialize
|
9
|
-
@cache =
|
9
|
+
@cache = {}
|
10
10
|
end
|
11
11
|
|
12
12
|
# @param index [Index]
|
@@ -36,10 +36,11 @@ module Fusuma
|
|
36
36
|
|
37
37
|
return search(index, location: location[0]) if context == {}
|
38
38
|
|
39
|
-
|
40
|
-
|
39
|
+
value = nil
|
40
|
+
location.find do |conf|
|
41
|
+
value = search(index, location: conf) if conf[:context] == context
|
41
42
|
end
|
42
|
-
|
43
|
+
value
|
43
44
|
end
|
44
45
|
|
45
46
|
# @param index [Index]
|
@@ -48,13 +49,12 @@ module Fusuma
|
|
48
49
|
# @return [Hash]
|
49
50
|
# @return [Object]
|
50
51
|
def search_with_cache(index, location:)
|
51
|
-
cache([index.cache_key, Searcher.context
|
52
|
+
cache([index.cache_key, Searcher.context]) do
|
52
53
|
search_with_context(index, location: location, context: Searcher.context)
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
56
57
|
def cache(key)
|
57
|
-
@cache ||= {}
|
58
58
|
key = key.join(",") if key.is_a? Array
|
59
59
|
if @cache.key?(key)
|
60
60
|
@cache[key]
|
@@ -71,36 +71,12 @@ module Fusuma
|
|
71
71
|
def next_location_cadidates(location, key)
|
72
72
|
[
|
73
73
|
location[key.symbol],
|
74
|
-
|
74
|
+
key.skippable && location
|
75
75
|
].compact
|
76
76
|
end
|
77
77
|
|
78
78
|
class << self
|
79
|
-
|
80
|
-
def conditions(&block)
|
81
|
-
{
|
82
|
-
nothing: -> { block.call },
|
83
|
-
skip: -> { Config::Searcher.skip { block.call } }
|
84
|
-
}
|
85
|
-
end
|
86
|
-
|
87
|
-
# Execute block with specified conditions
|
88
|
-
# @param conidtion [Symbol]
|
89
|
-
# @return [Object]
|
90
|
-
def with_condition(condition, &block)
|
91
|
-
conditions(&block)[condition].call
|
92
|
-
end
|
93
|
-
|
94
|
-
# Execute block with all conditions
|
95
|
-
# @return [Array<Symbol, Object>]
|
96
|
-
def find_condition(&block)
|
97
|
-
conditions(&block).find do |c, l|
|
98
|
-
result = l.call
|
99
|
-
return [c, result] if result
|
100
|
-
|
101
|
-
nil
|
102
|
-
end
|
103
|
-
end
|
79
|
+
attr_reader :context
|
104
80
|
|
105
81
|
# Search with context from load_streamed Config
|
106
82
|
# @param context [Hash]
|
@@ -112,52 +88,84 @@ module Fusuma
|
|
112
88
|
result
|
113
89
|
end
|
114
90
|
|
91
|
+
CONEXT_SEARCH_ORDER = [:no_context, :complete_match_context, :partial_match_context]
|
115
92
|
# Return a matching context from config
|
116
93
|
# @params request_context [Hash]
|
117
94
|
# @return [Hash]
|
118
|
-
def find_context(request_context, &block)
|
95
|
+
def find_context(request_context, fallbacks = CONEXT_SEARCH_ORDER, &block)
|
119
96
|
# Search in blocks in the following order.
|
120
|
-
# 1.
|
121
|
-
# 2.
|
122
|
-
# 3.
|
97
|
+
# 1. primary context(no context)
|
98
|
+
# 2. complete match config[:context] == request_context
|
99
|
+
# 3. partial match config[:context] =~ request_context
|
100
|
+
# no_context?(&block) ||
|
101
|
+
# complete_match_context(request_context, &block) ||
|
102
|
+
# partial_match_context(request_context, &block)
|
103
|
+
fallbacks.each do |method|
|
104
|
+
result = send(method, request_context, &block)
|
105
|
+
return result if result
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
# No context(primary context)
|
112
|
+
# @return [Hash]
|
113
|
+
# @return [NilClass]
|
114
|
+
def no_context(_request_context, &block)
|
115
|
+
return {} if with_context({}, &block)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Complete match request context
|
119
|
+
# @param request_context [Hash]
|
120
|
+
# @return [Hash] matched context
|
121
|
+
# @return [NilClass] if not matched
|
122
|
+
def complete_match_context(request_context, &block)
|
123
123
|
Config.instance.keymap.each do |config|
|
124
124
|
next unless config[:context] == request_context
|
125
|
-
return config[:context] if with_context(config[:context]
|
125
|
+
return config[:context] if with_context(config[:context], &block)
|
126
126
|
end
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
|
130
|
+
# One of multiple request contexts matched
|
131
|
+
# @param request_context [Hash]
|
132
|
+
# @return [Hash] matched context
|
133
|
+
# @return [NilClass] if not matched
|
134
|
+
def partial_match_context(request_context, &block)
|
127
135
|
if request_context.keys.size > 1
|
128
136
|
Config.instance.keymap.each do |config|
|
129
137
|
next if config[:context].nil?
|
130
138
|
|
131
139
|
next unless config[:context].all? { |k, v| request_context[k] == v }
|
132
|
-
return config[:context] if with_context(config[:context]
|
140
|
+
return config[:context] if with_context(config[:context], &block)
|
133
141
|
end
|
142
|
+
nil
|
134
143
|
end
|
135
|
-
return {} if with_context({}) { block.call }
|
136
|
-
end
|
137
|
-
|
138
|
-
attr_reader :context
|
139
|
-
|
140
|
-
def fallback?
|
141
|
-
@fallback
|
142
144
|
end
|
143
145
|
|
144
|
-
|
145
|
-
|
146
|
-
|
146
|
+
# Search context for plugin
|
147
|
+
# If the plugin_defaults key is a complete match,
|
148
|
+
# it is the default value for that plugin, so it is postponed.
|
149
|
+
# This is because prioritize overwriting by other plugins.
|
150
|
+
# The search order is as follows
|
151
|
+
# 1. complete match config[:context].key?(:plugin_defaults)
|
152
|
+
# 2. complete match config[:context] == request_context
|
153
|
+
# @param request_context [Hash]
|
154
|
+
# @return [Hash] matched context
|
155
|
+
# @return [NilClass] if not matched
|
156
|
+
def plugin_default_context(request_context, &block)
|
157
|
+
complete_match_context = nil
|
158
|
+
Config.instance.keymap.each do |config|
|
159
|
+
next unless config[:context]&.key?(:plugin_defaults)
|
147
160
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
@fallback = false
|
153
|
-
result
|
154
|
-
end
|
161
|
+
if config[:context][:plugin_defaults] == request_context[:plugin_defaults]
|
162
|
+
complete_match_context = config[:context]
|
163
|
+
next
|
164
|
+
end
|
155
165
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
@skip = false
|
160
|
-
result
|
166
|
+
return config[:context] if with_context(config[:context], &block)
|
167
|
+
end
|
168
|
+
complete_match_context
|
161
169
|
end
|
162
170
|
end
|
163
171
|
end
|
data/lib/fusuma/config.rb
CHANGED
@@ -4,6 +4,7 @@ require_relative "./multi_logger"
|
|
4
4
|
require_relative "./config/index"
|
5
5
|
require_relative "./config/searcher"
|
6
6
|
require_relative "./config/yaml_duplication_checker"
|
7
|
+
require_relative "./plugin/manager"
|
7
8
|
require_relative "./hash_support"
|
8
9
|
require "singleton"
|
9
10
|
require "yaml"
|
@@ -32,7 +33,7 @@ module Fusuma
|
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
35
|
-
attr_reader :
|
36
|
+
attr_reader :custom_path, :searcher
|
36
37
|
|
37
38
|
def initialize
|
38
39
|
@searcher = Searcher.new
|
@@ -45,17 +46,47 @@ module Fusuma
|
|
45
46
|
reload
|
46
47
|
end
|
47
48
|
|
49
|
+
def keymap
|
50
|
+
# FIXME: @keymap is not initialized when called from outside Fusuma::Runner like fusuma-senkey
|
51
|
+
@keymap || reload.keymap
|
52
|
+
end
|
53
|
+
|
48
54
|
def reload
|
55
|
+
plugin_defaults = plugin_defaults_paths.map do |default_yml|
|
56
|
+
{
|
57
|
+
context: {plugin_defaults: default_yml.split("/").last.delete_suffix(".yml")},
|
58
|
+
**validate(default_yml)[0]
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
config_path = find_config_filepath
|
63
|
+
@keymap = validate(config_path) | plugin_defaults
|
64
|
+
MultiLogger.info "reload config: #{config_path}"
|
65
|
+
|
66
|
+
# reset searcher cache
|
49
67
|
@searcher = Searcher.new
|
50
|
-
|
51
|
-
MultiLogger.info "reload config: #{path}"
|
52
|
-
@keymap = validate(path)
|
68
|
+
|
53
69
|
self
|
54
70
|
rescue InvalidFileError => e
|
55
71
|
MultiLogger.error e.message
|
56
72
|
exit 1
|
57
73
|
end
|
58
74
|
|
75
|
+
# @param key [Symbol]
|
76
|
+
# @param base [Config::Index]
|
77
|
+
# @return [Hash]
|
78
|
+
def fetch_config_params(key, base)
|
79
|
+
request_context = {plugin_defaults: base.keys.last.symbol.to_s}
|
80
|
+
fallbacks = [:no_context, :plugin_default_context]
|
81
|
+
Config::Searcher.find_context(request_context, fallbacks) do
|
82
|
+
ret = Config.search(base)
|
83
|
+
if ret&.key?(key)
|
84
|
+
return ret
|
85
|
+
end
|
86
|
+
end
|
87
|
+
{}
|
88
|
+
end
|
89
|
+
|
59
90
|
# @return [Hash] If check passes
|
60
91
|
# @raise [InvalidFileError] If check does not pass
|
61
92
|
def validate(path)
|
@@ -75,7 +106,6 @@ module Fusuma
|
|
75
106
|
end
|
76
107
|
|
77
108
|
# @param index [Index]
|
78
|
-
# @param context [Hash]
|
79
109
|
def search(index)
|
80
110
|
@searcher.search_with_cache(index, location: keymap)
|
81
111
|
end
|
@@ -95,7 +125,7 @@ module Fusuma
|
|
95
125
|
|
96
126
|
private
|
97
127
|
|
98
|
-
def
|
128
|
+
def find_config_filepath
|
99
129
|
filename = "fusuma/config.yml"
|
100
130
|
if custom_path
|
101
131
|
return expand_custom_path if File.exist?(expand_custom_path)
|
@@ -120,5 +150,12 @@ module Fusuma
|
|
120
150
|
def expand_default_path(filename)
|
121
151
|
File.expand_path "../../#{filename}", __FILE__
|
122
152
|
end
|
153
|
+
|
154
|
+
def plugin_defaults_paths
|
155
|
+
Plugin::Manager.load_paths.map do |plugin_path|
|
156
|
+
yml = plugin_path.gsub(/\.rb$/, ".yml")
|
157
|
+
yml if File.exist?(yml)
|
158
|
+
end.compact
|
159
|
+
end
|
123
160
|
end
|
124
161
|
end
|