procon_bypass_man-web 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.babelrc +6 -0
- data/.circleci/config.yml +73 -0
- data/.gitignore +12 -0
- data/.rspec +1 -0
- data/.rubocop.yml +26 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +97 -0
- data/LICENSE.txt +21 -0
- data/Procfile +2 -0
- data/README.md +43 -0
- data/Rakefile +4 -0
- data/bin/console +15 -0
- data/bin/pbm_web +7 -0
- data/bin/setup +8 -0
- data/jest.config.ts +194 -0
- data/lib/procon_bypass_man/web.rb +20 -0
- data/lib/procon_bypass_man/web/db.rb +33 -0
- data/lib/procon_bypass_man/web/migration/001_create_settings_table.sql +4 -0
- data/lib/procon_bypass_man/web/models/base_model.rb +47 -0
- data/lib/procon_bypass_man/web/models/setting.rb +22 -0
- data/lib/procon_bypass_man/web/public/bundle.js +2 -0
- data/lib/procon_bypass_man/web/public/bundle.js.LICENSE.txt +57 -0
- data/lib/procon_bypass_man/web/public/index.html +1 -0
- data/lib/procon_bypass_man/web/server.rb +139 -0
- data/lib/procon_bypass_man/web/setting_parser.rb +190 -0
- data/lib/procon_bypass_man/web/storage.rb +25 -0
- data/lib/procon_bypass_man/web/version.rb +7 -0
- data/package.json +48 -0
- data/procon_bypass_man-web.gemspec +36 -0
- data/src/app.tsx +5 -0
- data/src/components/button_setting.tsx +142 -0
- data/src/components/buttons_modal.tsx +110 -0
- data/src/components/buttons_setting.tsx +67 -0
- data/src/components/installable_macros.tsx +58 -0
- data/src/components/installable_modes.tsx +57 -0
- data/src/components/macro_settings.tsx +85 -0
- data/src/components/mode_settings.tsx +62 -0
- data/src/contexts/buttons_setting.ts +2 -0
- data/src/index.html +11 -0
- data/src/lib/button_state.test.ts +110 -0
- data/src/lib/button_state.ts +52 -0
- data/src/lib/button_state_diff.test.ts +123 -0
- data/src/lib/button_state_diff.ts +63 -0
- data/src/lib/buttons_setting_converter.test.ts +185 -0
- data/src/lib/buttons_setting_converter.ts +107 -0
- data/src/lib/http_client.ts +93 -0
- data/src/pages/bpm_page.tsx +92 -0
- data/src/pages/buttons_setting_page.tsx +281 -0
- data/src/pages/global_setting_page.tsx +83 -0
- data/src/pages/home.tsx +17 -0
- data/src/pages/recoding_mode_page.tsx +15 -0
- data/src/pages/top.tsx +107 -0
- data/src/reducers/layer_reducer.ts +120 -0
- data/src/types/button.ts +2 -0
- data/src/types/buttons_setting_type.ts +63 -0
- data/src/types/layer_key.ts +2 -0
- data/src/types/pbm_stats.ts +1 -0
- data/src/types/plugin.ts +43 -0
- data/tmp/.keep +0 -0
- data/tsconfig.json +75 -0
- data/webpack.config.js +56 -0
- data/yarn.lock +6815 -0
- metadata +150 -0
@@ -0,0 +1,123 @@
|
|
1
|
+
import { Button, buttons } from "../types/button";
|
2
|
+
import { ButtonInLayer, ButtonsInLayer, Layers, ButtonsSettingType } from "../types/buttons_setting_type";
|
3
|
+
import { ButtonStateDiff } from "./button_state_diff";
|
4
|
+
|
5
|
+
const makeLayer = () => {
|
6
|
+
const defaultLayer = buttons.reduce((acc, item) => { acc[item] = { open: false }; return acc; }, {} as ButtonsInLayer);
|
7
|
+
const upLayer = Object.assign({}, defaultLayer);
|
8
|
+
const downLayer = Object.assign({}, defaultLayer);
|
9
|
+
const leftLayer = Object.assign({}, defaultLayer);
|
10
|
+
const rightLayer = Object.assign({}, defaultLayer);
|
11
|
+
return {
|
12
|
+
prefix_keys_for_changing_layer: [] as Array<Button>,
|
13
|
+
layers: {
|
14
|
+
up: Object.assign({}, upLayer),
|
15
|
+
down: Object.assign({}, downLayer),
|
16
|
+
left: Object.assign({}, leftLayer),
|
17
|
+
right: Object.assign({}, rightLayer),
|
18
|
+
installed_macros: {},
|
19
|
+
installed_modes: {},
|
20
|
+
}
|
21
|
+
};
|
22
|
+
};
|
23
|
+
|
24
|
+
describe('全部ブランクの時', () => {
|
25
|
+
it('[]を返す', () => {
|
26
|
+
const before = Object.assign({}, makeLayer());
|
27
|
+
const after = Object.assign({}, makeLayer());
|
28
|
+
|
29
|
+
const actual = ButtonStateDiff({ before: before, after: after })
|
30
|
+
expect(actual).toStrictEqual([])
|
31
|
+
})
|
32
|
+
})
|
33
|
+
|
34
|
+
describe('keyで差分がある時', () => {
|
35
|
+
it('値を返す', () => {
|
36
|
+
const before = Object.assign({}, makeLayer());
|
37
|
+
const after = Object.assign({}, makeLayer());
|
38
|
+
|
39
|
+
before.prefix_keys_for_changing_layer = ["a"];
|
40
|
+
after.prefix_keys_for_changing_layer = ["y", "x"];
|
41
|
+
|
42
|
+
const actual = ButtonStateDiff({ before: before, after: after })
|
43
|
+
expect(actual).toStrictEqual(["key prefixは a => y,x になります"])
|
44
|
+
})
|
45
|
+
})
|
46
|
+
|
47
|
+
describe('layersで差分がある時', () => {
|
48
|
+
it('値を返す', () => {
|
49
|
+
const before = Object.assign({}, makeLayer());
|
50
|
+
const after = Object.assign({}, makeLayer());
|
51
|
+
|
52
|
+
before.prefix_keys_for_changing_layer = ["a"];
|
53
|
+
after.prefix_keys_for_changing_layer = ["a"];
|
54
|
+
before.layers.up.a = { flip: { if_pressed: ["y"], enable: true }, open: true }
|
55
|
+
before.layers.down.a = { flip: { if_pressed: ["y"], enable: true }, open: true }
|
56
|
+
after.layers.up.a = { flip: { if_pressed: ["a"], enable: false }, open: true }
|
57
|
+
|
58
|
+
const actual = ButtonStateDiff({ before: before, after: after })
|
59
|
+
expect(actual).toStrictEqual([
|
60
|
+
"layer up の a を変更しました",
|
61
|
+
"layer down の a を変更しました",
|
62
|
+
])
|
63
|
+
})
|
64
|
+
})
|
65
|
+
|
66
|
+
describe('installed_macrosで差分がある時', () => {
|
67
|
+
it('値を返す', () => {
|
68
|
+
const before = Object.assign({}, makeLayer());
|
69
|
+
const after = Object.assign({}, makeLayer());
|
70
|
+
|
71
|
+
before.layers.installed_macros = { a: true }
|
72
|
+
|
73
|
+
const actual = ButtonStateDiff({ before: before, after: after })
|
74
|
+
expect(actual).toStrictEqual([
|
75
|
+
"インストール可能なマクロを変更しました"
|
76
|
+
])
|
77
|
+
})
|
78
|
+
})
|
79
|
+
|
80
|
+
describe('layer.x.macroで差分がある時', () => {
|
81
|
+
it('値を返す', () => {
|
82
|
+
const before = Object.assign({}, makeLayer());
|
83
|
+
const after = Object.assign({}, makeLayer());
|
84
|
+
|
85
|
+
before.layers.up.macro = { a: [] }
|
86
|
+
after.layers.up.macro = { a: ["b"] }
|
87
|
+
|
88
|
+
const actual = ButtonStateDiff({ before: before, after: after })
|
89
|
+
expect(actual).toStrictEqual([
|
90
|
+
"layer up の マクロ を変更しました"
|
91
|
+
])
|
92
|
+
})
|
93
|
+
})
|
94
|
+
|
95
|
+
describe('installed_modesで差分がある時', () => {
|
96
|
+
it('値を返す', () => {
|
97
|
+
const before = Object.assign({}, makeLayer());
|
98
|
+
const after = Object.assign({}, makeLayer());
|
99
|
+
|
100
|
+
before.layers.installed_modes = { b: true }
|
101
|
+
|
102
|
+
const actual = ButtonStateDiff({ before: before, after: after })
|
103
|
+
expect(actual).toStrictEqual([
|
104
|
+
"インストール可能なモードを変更しました"
|
105
|
+
])
|
106
|
+
})
|
107
|
+
})
|
108
|
+
|
109
|
+
describe('layer.x.modeで差分がある時', () => {
|
110
|
+
it('値を返す', () => {
|
111
|
+
const before = Object.assign({}, makeLayer());
|
112
|
+
const after = Object.assign({}, makeLayer());
|
113
|
+
|
114
|
+
before.layers.up.mode = {}
|
115
|
+
after.layers.up.mode = { a: true }
|
116
|
+
|
117
|
+
const actual = ButtonStateDiff({ before: before, after: after })
|
118
|
+
expect(actual).toStrictEqual([
|
119
|
+
"layer up の モード を変更しました"
|
120
|
+
])
|
121
|
+
})
|
122
|
+
})
|
123
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
import { Button, buttons } from "../types/button";
|
2
|
+
import { ButtonInLayer, ButtonsInLayer, Layers, ButtonsSettingType, Macro, ModeTable } from "../types/buttons_setting_type";
|
3
|
+
import { LayerKey, layerKeys } from "../types/layer_key";
|
4
|
+
import { diff } from 'deep-object-diff';
|
5
|
+
|
6
|
+
type Props = {
|
7
|
+
before: ButtonsSettingType;
|
8
|
+
after: ButtonsSettingType;
|
9
|
+
};
|
10
|
+
|
11
|
+
export const ButtonStateDiff = ({ before, after }: Props): Array<string> => {
|
12
|
+
const changes = [] as Array<string>;
|
13
|
+
|
14
|
+
if(!before || !after || !before.layers) { return changes; };
|
15
|
+
|
16
|
+
if(before.layers.installed_macros && after.layers.installed_macros) {
|
17
|
+
const installedMacrosDiffResult = diff(before.layers.installed_macros, after.layers.installed_macros);
|
18
|
+
if(Object.keys(installedMacrosDiffResult || []).length > 0) {
|
19
|
+
changes.push("インストール可能なマクロを変更しました")
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
if(before.layers.installed_modes && after.layers.installed_modes) {
|
24
|
+
const installedModesDiffResult = diff(before.layers.installed_modes, after.layers.installed_modes);
|
25
|
+
if(Object.keys(installedModesDiffResult || []).length > 0) {
|
26
|
+
changes.push("インストール可能なモードを変更しました")
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
if(before.prefix_keys_for_changing_layer && after.prefix_keys_for_changing_layer) {
|
31
|
+
if(before.prefix_keys_for_changing_layer.toString() === after.prefix_keys_for_changing_layer.toString()) {
|
32
|
+
// no-op
|
33
|
+
} else {
|
34
|
+
changes.push(`key prefixは ${before.prefix_keys_for_changing_layer} => ${after.prefix_keys_for_changing_layer} になります`)
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
layerKeys.forEach((layerKey) => {
|
39
|
+
const beforeMacro = before.layers[layerKey].macro || {} as Macro
|
40
|
+
const afterMacro = after.layers[layerKey].macro || {} as Macro
|
41
|
+
const macroDiffResult = diff(beforeMacro, afterMacro);
|
42
|
+
if(Object.keys(macroDiffResult || []).length > 0) {
|
43
|
+
changes.push(`layer ${layerKey} の マクロ を変更しました`)
|
44
|
+
}
|
45
|
+
|
46
|
+
const beforeMode = before.layers[layerKey].mode || {} as ModeTable
|
47
|
+
const afterMode = after.layers[layerKey].mode || {} as ModeTable
|
48
|
+
const modeDiffResult = diff(beforeMode, afterMode);
|
49
|
+
if(Object.keys(modeDiffResult || []).length > 0) {
|
50
|
+
changes.push(`layer ${layerKey} の モード を変更しました`)
|
51
|
+
}
|
52
|
+
|
53
|
+
buttons.forEach((b) => {
|
54
|
+
// どの項目が何に変化したかを出力したかったがめんどくさすぎたのでやめた
|
55
|
+
const diffResult = diff(before.layers[layerKey as LayerKey][b], after.layers[layerKey as LayerKey][b]);
|
56
|
+
if(Object.keys(diffResult || []).length > 0) {
|
57
|
+
changes.push(`layer ${layerKey} の ${b} を変更しました`)
|
58
|
+
}
|
59
|
+
})
|
60
|
+
})
|
61
|
+
|
62
|
+
return changes;
|
63
|
+
}
|
@@ -0,0 +1,185 @@
|
|
1
|
+
import { ButtonsSettingConverter } from "./buttons_setting_converter";
|
2
|
+
import { Button, buttons } from "../types/button";
|
3
|
+
import { ButtonsInLayer } from "../types/buttons_setting_type";
|
4
|
+
import yaml from "js-yaml";
|
5
|
+
import _ from 'lodash';
|
6
|
+
|
7
|
+
describe('値があるとき', () => {
|
8
|
+
const prefixKeys = ["y", "l"] as Array<Button>;
|
9
|
+
const defaultLayer = buttons.reduce((acc, item) => { acc[item] = { open: false }; return acc; }, {} as ButtonsInLayer);
|
10
|
+
const upLayer = _.cloneDeep(defaultLayer);
|
11
|
+
const downLayer = _.cloneDeep(defaultLayer);
|
12
|
+
const leftLayer = _.cloneDeep(defaultLayer);
|
13
|
+
const rightLayer = _.cloneDeep(defaultLayer);
|
14
|
+
upLayer.a = { flip: { if_pressed: [], enable: true, force_neutral: ["y"] }, open: true }
|
15
|
+
upLayer.b = { flip: { if_pressed: ["a"], enable: true, force_neutral: ["y"] }, open: true }
|
16
|
+
upLayer.x = { flip: { if_pressed: ["a"], enable: false, force_neutral: ["y"] }, open: true }
|
17
|
+
upLayer.y = { flip: { if_pressed: [], enable: false, force_neutral: [] }, open: true }
|
18
|
+
downLayer.a = { flip: { if_pressed: ["a", "b"], enable: true, force_neutral: ["y", "x"] }, open: true }
|
19
|
+
leftLayer.a = { remap: { to: ["b", "y"] }, open: true }
|
20
|
+
const layers = {
|
21
|
+
up: upLayer,
|
22
|
+
down: downLayer,
|
23
|
+
left: leftLayer,
|
24
|
+
right: rightLayer,
|
25
|
+
};
|
26
|
+
|
27
|
+
it('validなyamlであること', () => {
|
28
|
+
const actual = ButtonsSettingConverter({ prefixKeys: prefixKeys, layers: layers })
|
29
|
+
yaml.load(actual)
|
30
|
+
})
|
31
|
+
|
32
|
+
it('定義が出力されること', () => {
|
33
|
+
const actual = ButtonsSettingConverter({ prefixKeys: prefixKeys, layers: layers })
|
34
|
+
const expected = `version: 1.0
|
35
|
+
setting: |-
|
36
|
+
|
37
|
+
|
38
|
+
prefix_keys_for_changing_layer %i(y l)
|
39
|
+
|
40
|
+
layer :up do
|
41
|
+
flip :a, force_neutral: %i(y)
|
42
|
+
flip :b, if_pressed: %i(a), force_neutral: %i(y)
|
43
|
+
|
44
|
+
end
|
45
|
+
layer :right do
|
46
|
+
|
47
|
+
end
|
48
|
+
layer :down do
|
49
|
+
flip :a, if_pressed: %i(a b), force_neutral: %i(y x)
|
50
|
+
|
51
|
+
end
|
52
|
+
layer :left do
|
53
|
+
remap :a, to: %i(b y)
|
54
|
+
|
55
|
+
end`;
|
56
|
+
expect(actual).toBe(expected);
|
57
|
+
})
|
58
|
+
})
|
59
|
+
|
60
|
+
describe('macroがあるとき', () => {
|
61
|
+
const prefixKeys = ["y", "l"] as Array<Button>;
|
62
|
+
const defaultLayer = buttons.reduce((acc, item) => { acc[item] = { open: false }; return acc; }, {} as ButtonsInLayer);
|
63
|
+
const upLayer = _.cloneDeep(defaultLayer);
|
64
|
+
upLayer.macro = { "ProconBypassMan::Splatoon2::Macro::FastReturn": ["y", "l"] }
|
65
|
+
const downLayer = _.cloneDeep(defaultLayer);
|
66
|
+
const leftLayer = _.cloneDeep(defaultLayer);
|
67
|
+
const rightLayer = _.cloneDeep(defaultLayer);
|
68
|
+
const layers = {
|
69
|
+
up: upLayer,
|
70
|
+
down: downLayer,
|
71
|
+
left: leftLayer,
|
72
|
+
right: rightLayer,
|
73
|
+
installed_macros: {
|
74
|
+
"ProconBypassMan::Splatoon2::Macro::FastReturn": true,
|
75
|
+
"ProconBypassMan::Sumabura::Macro::Foo": true,
|
76
|
+
"HOGE": false,
|
77
|
+
}
|
78
|
+
};
|
79
|
+
|
80
|
+
it('installed_macroを出力すること', () => {
|
81
|
+
const actual = ButtonsSettingConverter({ prefixKeys: prefixKeys, layers: layers })
|
82
|
+
const expected = `version: 1.0
|
83
|
+
setting: |-
|
84
|
+
install_macro_plugin ProconBypassMan::Splatoon2::Macro::FastReturn
|
85
|
+
install_macro_plugin ProconBypassMan::Sumabura::Macro::Foo
|
86
|
+
|
87
|
+
prefix_keys_for_changing_layer %i(y l)
|
88
|
+
|
89
|
+
layer :up do
|
90
|
+
macro ProconBypassMan::Splatoon2::Macro::FastReturn, if_pressed: %i(y l)
|
91
|
+
end
|
92
|
+
layer :right do
|
93
|
+
|
94
|
+
end
|
95
|
+
layer :down do
|
96
|
+
|
97
|
+
end
|
98
|
+
layer :left do
|
99
|
+
|
100
|
+
end`;
|
101
|
+
expect(actual).toBe(expected);
|
102
|
+
})
|
103
|
+
})
|
104
|
+
|
105
|
+
describe('modeがあるとき', () => {
|
106
|
+
const prefixKeys = ["y", "l"] as Array<Button>;
|
107
|
+
const defaultLayer = buttons.reduce((acc, item) => { acc[item] = { open: false }; return acc; }, {} as ButtonsInLayer);
|
108
|
+
const upLayer = _.cloneDeep(defaultLayer);
|
109
|
+
upLayer.mode = { "ProconBypassMan::Splatoon2::Mode::Guruguru": true }
|
110
|
+
const downLayer = _.cloneDeep(defaultLayer);
|
111
|
+
const leftLayer = _.cloneDeep(defaultLayer);
|
112
|
+
const rightLayer = _.cloneDeep(defaultLayer);
|
113
|
+
const layers = {
|
114
|
+
up: upLayer,
|
115
|
+
down: downLayer,
|
116
|
+
left: leftLayer,
|
117
|
+
right: rightLayer,
|
118
|
+
installed_modes: {
|
119
|
+
"ProconBypassMan::Splatoon2::Mode::Guruguru": true,
|
120
|
+
"unknown": false,
|
121
|
+
}
|
122
|
+
};
|
123
|
+
|
124
|
+
it('installed_modeを出力すること', () => {
|
125
|
+
const actual = ButtonsSettingConverter({ prefixKeys: prefixKeys, layers: layers })
|
126
|
+
const expected = `version: 1.0
|
127
|
+
setting: |-
|
128
|
+
|
129
|
+
install_mode_plugin ProconBypassMan::Splatoon2::Mode::Guruguru
|
130
|
+
prefix_keys_for_changing_layer %i(y l)
|
131
|
+
|
132
|
+
layer :up, mode: ProconBypassMan::Splatoon2::Mode::Guruguru do
|
133
|
+
|
134
|
+
end
|
135
|
+
layer :right do
|
136
|
+
|
137
|
+
end
|
138
|
+
layer :down do
|
139
|
+
|
140
|
+
end
|
141
|
+
layer :left do
|
142
|
+
|
143
|
+
end`;
|
144
|
+
expect(actual).toBe(expected);
|
145
|
+
})
|
146
|
+
})
|
147
|
+
|
148
|
+
describe('全部からのとき', () => {
|
149
|
+
const prefixKeys = ["y", "l"] as Array<Button>;
|
150
|
+
const defaultLayer = buttons.reduce((acc, item) => { acc[item] = { open: false }; return acc; }, {} as ButtonsInLayer);
|
151
|
+
const layers = {
|
152
|
+
up: defaultLayer,
|
153
|
+
down: defaultLayer,
|
154
|
+
left: defaultLayer,
|
155
|
+
right: defaultLayer,
|
156
|
+
};
|
157
|
+
|
158
|
+
it('validなyamlであること', () => {
|
159
|
+
const actual = ButtonsSettingConverter({ prefixKeys: prefixKeys, layers: layers })
|
160
|
+
yaml.load(actual)
|
161
|
+
})
|
162
|
+
|
163
|
+
it('全部空になること', () => {
|
164
|
+
const actual = ButtonsSettingConverter({ prefixKeys: prefixKeys, layers: layers })
|
165
|
+
const expected = `version: 1.0
|
166
|
+
setting: |-
|
167
|
+
|
168
|
+
|
169
|
+
prefix_keys_for_changing_layer %i(y l)
|
170
|
+
|
171
|
+
layer :up do
|
172
|
+
|
173
|
+
end
|
174
|
+
layer :right do
|
175
|
+
|
176
|
+
end
|
177
|
+
layer :down do
|
178
|
+
|
179
|
+
end
|
180
|
+
layer :left do
|
181
|
+
|
182
|
+
end`;
|
183
|
+
expect(actual).toBe(expected);
|
184
|
+
})
|
185
|
+
})
|
@@ -0,0 +1,107 @@
|
|
1
|
+
import { LayerKey, layerKeys } from "../types/layer_key";
|
2
|
+
import { Macro, Remap, Flip, Layers, ButtonsInLayer } from "../types/buttons_setting_type";
|
3
|
+
import { Button, buttons } from "../types/button";
|
4
|
+
|
5
|
+
type Props = {
|
6
|
+
prefixKeys: Array<Button>;
|
7
|
+
layers: Layers;
|
8
|
+
};
|
9
|
+
export const ButtonsSettingConverter = ({ prefixKeys, layers }: Props) => {
|
10
|
+
const layerBlock = (layerKey: LayerKey) => {
|
11
|
+
const modeTable = layers[layerKey].mode || {}
|
12
|
+
const currentMode = Object.keys(modeTable).toString();
|
13
|
+
if(currentMode === "disable" || currentMode === '') {
|
14
|
+
return `layer :${layerKey} do`;
|
15
|
+
} else {
|
16
|
+
const modeOption = `, mode: ${currentMode}`
|
17
|
+
return `layer :${layerKey}${modeOption} do`;
|
18
|
+
}
|
19
|
+
}
|
20
|
+
type defineButtonMethodProps = {
|
21
|
+
layer: ButtonsInLayer;
|
22
|
+
button: Button;
|
23
|
+
};
|
24
|
+
const buttons_with_macro = buttons
|
25
|
+
const createButtonMethod = ({ layer , button }: defineButtonMethodProps) => {
|
26
|
+
const flip = layer[button].flip;
|
27
|
+
const remap = layer[button].remap;
|
28
|
+
if(flip && flip.enable) {
|
29
|
+
if(!flip.if_pressed) { return }
|
30
|
+
if(flip.if_pressed.length === 0) {
|
31
|
+
return `flip :${button}${(flip.force_neutral || "") && `, force_neutral: %i(${flip.force_neutral?.join(" ")})`}`;
|
32
|
+
} else {
|
33
|
+
// ex) flip :a
|
34
|
+
// flip :a, if_pressed: [:b]
|
35
|
+
return `flip :${button}${(flip.if_pressed || "") && `, if_pressed: %i(${flip.if_pressed?.join(" ")})`}${(flip.force_neutral || "") && `, force_neutral: %i(${flip.force_neutral?.join(" ")})`}`;
|
36
|
+
}
|
37
|
+
} else { // flipとremapは共存できないのでelseにする
|
38
|
+
if(remap) {
|
39
|
+
return `remap :${button}${(remap.to || "") && `, to: %i(${remap.to.join(" ")})`}`;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
return null;
|
43
|
+
}
|
44
|
+
|
45
|
+
const layerBlockIndent = " ";
|
46
|
+
const topLevelIndent = " ";
|
47
|
+
if(!layers.installed_macros) { layers.installed_macros = {} };
|
48
|
+
if(!layers.installed_modes) { layers.installed_modes = {} };
|
49
|
+
if(!layers.up.macro) { layers.up.macro = {} };
|
50
|
+
if(!layers.down.macro) { layers.down.macro = {} };
|
51
|
+
if(!layers.right.macro) { layers.right.macro = {} };
|
52
|
+
if(!layers.left.macro) { layers.left.macro = {} };
|
53
|
+
const installedMacroNames = Object.entries(layers.installed_macros).filter((k, i) => k[1]).map(v => v[0]);
|
54
|
+
const installedModeNames = Object.entries(layers.installed_modes).filter((k, i) => k[1]).map(v => v[0]);
|
55
|
+
|
56
|
+
const expandMacroInLayer = (macro: Macro) => {
|
57
|
+
return Object.entries(macro).map((m) => {
|
58
|
+
const name = m[0] as string;
|
59
|
+
const ifPressed = m[1] as Array<Button>;
|
60
|
+
return `${layerBlockIndent}macro ${name}, if_pressed: %i(${ifPressed.join(" ")})` }
|
61
|
+
)
|
62
|
+
};
|
63
|
+
|
64
|
+
return(
|
65
|
+
`version: 1.0
|
66
|
+
setting: |-
|
67
|
+
${installedMacroNames.map((name) => `${topLevelIndent}install_macro_plugin ${name}`).join("\n")}
|
68
|
+
${installedModeNames.map((name) => `${topLevelIndent}install_mode_plugin ${name}`).join("\n")}
|
69
|
+
prefix_keys_for_changing_layer %i(${prefixKeys.join(" ")})
|
70
|
+
|
71
|
+
${
|
72
|
+
buttons.reduce((a, b) => {
|
73
|
+
const m = createButtonMethod({ layer: layers.up, button: b })
|
74
|
+
if(m) { a = a + `\n${layerBlockIndent}` + m }
|
75
|
+
return a;
|
76
|
+
}, layerBlock("up"))
|
77
|
+
}
|
78
|
+
${expandMacroInLayer(layers.up.macro)}
|
79
|
+
end
|
80
|
+
${
|
81
|
+
buttons.reduce((a, b) => {
|
82
|
+
const m = createButtonMethod({ layer: layers.right, button: b })
|
83
|
+
if(m) { a = a + `\n${layerBlockIndent}` + m }
|
84
|
+
return a;
|
85
|
+
}, layerBlock("right"))
|
86
|
+
}
|
87
|
+
${expandMacroInLayer(layers.down.macro)}
|
88
|
+
end
|
89
|
+
${
|
90
|
+
buttons.reduce((a, b) => {
|
91
|
+
const m = createButtonMethod({ layer: layers.down, button: b })
|
92
|
+
if(m) { a = a + `\n${layerBlockIndent}` + m }
|
93
|
+
return a;
|
94
|
+
}, layerBlock("down"))
|
95
|
+
}
|
96
|
+
${expandMacroInLayer(layers.down.macro)}
|
97
|
+
end
|
98
|
+
${
|
99
|
+
buttons.reduce((a, b) => {
|
100
|
+
const m = createButtonMethod({ layer: layers.left, button: b })
|
101
|
+
if(m) { a = a + `\n${layerBlockIndent}` + m }
|
102
|
+
return a;
|
103
|
+
}, layerBlock("left"))
|
104
|
+
}
|
105
|
+
${expandMacroInLayer(layers.left.macro)}
|
106
|
+
end`)
|
107
|
+
}
|