1
1
# タップダンス: 1つのキーが3つ、5つまたは100の異なる動作をします
2
2
3
3
<!-- -
4
- original document: 0.10.33 :docs/feature_tap_dance.md
5
- git diff 0.10.33 HEAD -- docs/feature_tap_dance.md | cat
4
+ original document: 0.13.15 :docs/feature_tap_dance.md
5
+ git diff 0.13.15 HEAD -- docs/feature_tap_dance.md | cat
6
6
-->
7
7
8
8
## イントロダクション : id =introduction
22
22
23
23
`TAPPING_TERM` の時間は、あなたのタップダンスのキーのタップとタップの間の時間として許可された最大の時間で、ミリ秒単位で計測されます。例えば、もし、あなたがこの上にある `#define` ステートメントを使い、1回タップすると `Space` が送信され、2回タップすると `Enter` が送信されるタップダンスキーをセットアップした場合、175ミリ秒以内に2回キーをタップすれば `ENT` だけが送信されるでしょう。もし、1回タップしてから175ミリ秒以上待ってからもう一度タップすると、`SPC SPC` が送信されます。
24
24
25
- 次に、いくつかのタップダンスのキーを定義するためには、`TD()` マクロを使うのが最も簡単です。これは数字を受け取り、この数字は後で `tap_dance-actions ` 配列のインデックスとして使われます。
25
+ 次に、いくつかのタップダンスのキーを定義するためには、`TD()` マクロを使うのが最も簡単です。これは数字を受け取り、この数字は後で `tap_dance_actions ` 配列のインデックスとして使われます。
26
26
27
27
その後、`tap_dance_actions` 配列を使って、タップダンスキーを押した時のアクションを定義します。現在は、5つの可能なオプションがあります:
28
28
@@ -85,7 +85,7 @@ qk_tap_dance_action_t tap_dance_actions[] = {
85
85
[TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS),
86
86
};
87
87
88
- // キーコードの代わりにタップダンスキーを追加します
88
+ // キーマップにキーコードの代わりにタップダンスの項目を追加します
89
89
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
90
90
// ...
91
91
TD(TD_ESC_CAPS)
@@ -215,28 +215,30 @@ qk_tap_dance_action_t tap_dance_actions[] = {
215
215
`keymap.c` ファイルの先頭、つまりキーマップの前に、以下のコードを追加します。
216
216
217
217
```c
218
+ typedef enum {
219
+ TD_NONE,
220
+ TD_UNKNOWN,
221
+ TD_SINGLE_TAP,
222
+ TD_SINGLE_HOLD,
223
+ TD_DOUBLE_TAP,
224
+ TD_DOUBLE_HOLD,
225
+ TD_DOUBLE_SINGLE_TAP, // Send two single taps
226
+ TD_TRIPLE_TAP,
227
+ TD_TRIPLE_HOLD
228
+ } td_state_t;
229
+
218
230
typedef struct {
219
231
bool is_press_action;
220
- uint8_t state;
221
- } tap;
222
-
223
- enum {
224
- SINGLE_TAP = 1,
225
- SINGLE_HOLD,
226
- DOUBLE_TAP,
227
- DOUBLE_HOLD,
228
- DOUBLE_SINGLE_TAP, // シングルタップを2回送信
229
- TRIPLE_TAP,
230
- TRIPLE_HOLD
231
- };
232
+ td_state_t state;
233
+ } td_tap_t;
232
234
233
235
// タップダンスの列挙型
234
236
enum {
235
237
X_CTL,
236
238
SOME_OTHER_DANCE
237
239
};
238
240
239
- uint8_t cur_dance(qk_tap_dance_state_t *state);
241
+ td_state_t cur_dance(qk_tap_dance_state_t *state);
240
242
241
243
// xタップダンスのための関数。キーマップで利用できるようにするため、ここに置きます。
242
244
void x_finished(qk_tap_dance_state_t *state, void *user_data);
@@ -273,63 +275,63 @@ void x_reset(qk_tap_dance_state_t *state, void *user_data);
273
275
* 一般的な単語で2回続けて使われる文字でないこと。例えば 'pepper' 中の 'p'。もしタップダンス機能が
274
276
* 文字 'p' に存在する場合、'pepper' という単語は入力するのが非常にいらだたしいものになるでしょう。
275
277
*
276
- * 3つ目の点については、'DOUBLE_SINGLE_TAP ' が存在しますが、これは完全にはテストされていません
278
+ * 3つ目の点については、'TD_DOUBLE_SINGLE_TAP ' が存在しますが、これは完全にはテストされていません
277
279
*
278
280
*/
279
- uint8_t cur_dance (qk_tap_dance_state_t * state) {
281
+ td_state_t cur_dance (qk_tap_dance_state_t * state) {
280
282
if (state->count == 1) {
281
- if (state->interrupted || !state->pressed) return SINGLE_TAP ;
283
+ if (state->interrupted || !state->pressed) return TD_SINGLE_TAP ;
282
284
// キーは割り込まれていませんが、まだ押し続けられています。'HOLD' を送信することを意味します。
283
- else return SINGLE_HOLD ;
285
+ else return TD_SINGLE_HOLD ;
284
286
} else if (state->count == 2) {
285
- // DOUBLE_SINGLE_TAP は "pepper" と入力することと、'pp' と入力したときに実際に
287
+ // TD_DOUBLE_SINGLE_TAP は "pepper" と入力することと、'pp' と入力したときに実際に
286
288
// ダブルタップしたい場合とを区別するためのものです。
287
289
// この戻り値の推奨されるユースケースは、'ダブルタップ' 動作やマクロではなく、
288
290
// そのキーの2つのキー入力を送信したい場合です。
289
- if (state->interrupted) return DOUBLE_SINGLE_TAP ;
290
- else if (state->pressed) return DOUBLE_HOLD ;
291
- else return DOUBLE_TAP ;
291
+ if (state->interrupted) return TD_DOUBLE_SINGLE_TAP ;
292
+ else if (state->pressed) return TD_DOUBLE_HOLD ;
293
+ else return TD_DOUBLE_TAP ;
292
294
}
293
295
294
296
// 誰も同じ文字を3回入力しようとしていないと仮定します(少なくとも高速には)。
295
297
// タップダンスキーが 'KC_W' で、"www." と高速に入力したい場合、ここに例外を追加して
296
- // 'TRIPLE_SINGLE_TAP ' を返し、'DOUBLE_SINGLE_TAP ' のようにその列挙型を定義する必要があります。
298
+ // 'TD_TRIPLE_SINGLE_TAP ' を返し、'TD_DOUBLE_SINGLE_TAP ' のようにその列挙型を定義する必要があります。
297
299
if (state->count == 3) {
298
- if (state->interrupted || !state->pressed) return TRIPLE_TAP ;
299
- else return TRIPLE_HOLD ;
300
- } else return 8; // マジックナンバー。いつかこのメソッドはより多くの押下に対して機能するよう拡張されるでしょう
300
+ if (state->interrupted || !state->pressed) return TD_TRIPLE_TAP ;
301
+ else return TD_TRIPLE_HOLD ;
302
+ } else return TD_UNKNOWN;
301
303
}
302
304
303
- //'x' タップダンスの 'tap ' のインスタンスを生成します。
304
- static tap xtap_state = {
305
+ //'x' タップダンスの 'td_tap_t ' のインスタンスを生成します。
306
+ static td_tap_t xtap_state = {
305
307
.is_press_action = true,
306
- .state = 0
308
+ .state = TD_NONE
307
309
};
308
310
309
311
void x_finished(qk_tap_dance_state_t * state, void * user_data) {
310
312
xtap_state.state = cur_dance(state);
311
313
switch (xtap_state.state) {
312
- case SINGLE_TAP : register_code(KC_X); break;
313
- case SINGLE_HOLD : register_code(KC_LCTRL); break;
314
- case DOUBLE_TAP : register_code(KC_ESC); break;
315
- case DOUBLE_HOLD : register_code(KC_LALT); break;
314
+ case TD_SINGLE_TAP : register_code(KC_X); break;
315
+ case TD_SINGLE_HOLD : register_code(KC_LCTRL); break;
316
+ case TD_DOUBLE_TAP : register_code(KC_ESC); break;
317
+ case TD_DOUBLE_HOLD : register_code(KC_LALT); break;
316
318
// 最後の case は高速入力用です。キーが ` f ` であると仮定します:
317
319
// 例えば、` buffer ` という単語を入力するとき、` Esc ` ではなく ` ff ` を送信するようにします。
318
320
// 高速入力時に ` ff ` と入力するには、次の文字は ` TAPPING_TERM ` 以内に入力する必要があります。
319
321
// ` TAPPING_TERM ` はデフォルトでは 200ms です。
320
- case DOUBLE_SINGLE_TAP : tap_code(KC_X); register_code(KC_X);
322
+ case TD_DOUBLE_SINGLE_TAP : tap_code(KC_X); register_code(KC_X);
321
323
}
322
324
}
323
325
324
326
void x_reset(qk_tap_dance_state_t * state, void * user_data) {
325
327
switch (xtap_state.state) {
326
- case SINGLE_TAP : unregister_code(KC_X); break;
327
- case SINGLE_HOLD : unregister_code(KC_LCTRL); break;
328
- case DOUBLE_TAP : unregister_code(KC_ESC); break;
329
- case DOUBLE_HOLD : unregister_code(KC_LALT);
330
- case DOUBLE_SINGLE_TAP : unregister_code(KC_X);
328
+ case TD_SINGLE_TAP : unregister_code(KC_X); break;
329
+ case TD_SINGLE_HOLD : unregister_code(KC_LCTRL); break;
330
+ case TD_DOUBLE_TAP : unregister_code(KC_ESC); break;
331
+ case TD_DOUBLE_HOLD : unregister_code(KC_LALT);
332
+ case TD_DOUBLE_SINGLE_TAP : unregister_code(KC_X);
331
333
}
332
- xtap_state.state = 0 ;
334
+ xtap_state.state = TD_NONE ;
333
335
}
334
336
335
337
qk_tap_dance_action_t tap_dance_actions[ ] = {
@@ -357,9 +359,11 @@ enum td_keycodes {
357
359
358
360
// 必要な数のタップダンス状態を含むタイプを定義します
359
361
typedef enum {
360
- SINGLE_TAP,
361
- SINGLE_HOLD,
362
- DOUBLE_SINGLE_TAP
362
+ TD_NONE,
363
+ TD_UNKNOWN,
364
+ TD_SINGLE_TAP,
365
+ TD_SINGLE_HOLD,
366
+ TD_DOUBLE_SINGLE_TAP
363
367
} td_state_t;
364
368
365
369
// タップダンスの状態の型のグローバルインスタンスを作ります
@@ -368,7 +372,7 @@ static td_state_t td_state;
368
372
// タップダンス関数を宣言します:
369
373
370
374
// 現在のタップダンスの状態を特定するための関数
371
- uint8_t cur_dance(qk_tap_dance_state_t *state);
375
+ td_state_t cur_dance(qk_tap_dance_state_t *state);
372
376
373
377
// それぞれのタップダンスキーコードに適用する `finished` と `reset` 関数
374
378
void altlp_finished(qk_tap_dance_state_t *state, void *user_data);
@@ -379,42 +383,42 @@ void altlp_reset(qk_tap_dance_state_t *state, void *user_data);
379
383
380
384
``` c
381
385
// 返却するタップダンス状態を特定します
382
- uint8_t cur_dance (qk_tap_dance_state_t * state) {
386
+ td_state_t cur_dance (qk_tap_dance_state_t * state) {
383
387
if (state->count == 1) {
384
- if (state->interrupted || !state->pressed) return SINGLE_TAP ;
385
- else return SINGLE_HOLD ;
388
+ if (state->interrupted || !state->pressed) return TD_SINGLE_TAP ;
389
+ else return TD_SINGLE_HOLD ;
386
390
}
387
391
388
- if (state->count == 2) return DOUBLE_SINGLE_TAP ;
389
- else return 3 ; // 上記で返却する最大の状態の値より大きい任意の数
392
+ if (state->count == 2) return TD_DOUBLE_SINGLE_TAP ;
393
+ else return TD_UNKNOWN ; // 上記で返却する最大の状態の値より大きい任意の数
390
394
}
391
395
392
396
// 定義する各タップダンスキーコードのとりうる状態を制御します:
393
397
394
398
void altlp_finished(qk_tap_dance_state_t * state, void * user_data) {
395
399
td_state = cur_dance(state);
396
400
switch (td_state) {
397
- case SINGLE_TAP :
401
+ case TD_SINGLE_TAP :
398
402
register_code16(KC_LPRN);
399
403
break;
400
- case SINGLE_HOLD :
404
+ case TD_SINGLE_HOLD :
401
405
register_mods(MOD_BIT(KC_LALT)); // レイヤータップキーの場合、ここでは ` layer_on(_MY_LAYER) ` を使います
402
406
break;
403
- case DOUBLE_SINGLE_TAP : // タップ時間内に2つの括弧 ` (( ` の入れ子を可能にします
407
+ case TD_DOUBLE_SINGLE_TAP : // タップ時間内に2つの括弧 ` (( ` の入れ子を可能にします
404
408
tap_code16(KC_LPRN);
405
409
register_code16(KC_LPRN);
406
410
}
407
411
}
408
412
409
413
void altlp_reset(qk_tap_dance_state_t * state, void * user_data) {
410
414
switch (td_state) {
411
- case SINGLE_TAP :
415
+ case TD_SINGLE_TAP :
412
416
unregister_code16(KC_LPRN);
413
417
break;
414
- case SINGLE_HOLD :
418
+ case TD_SINGLE_HOLD :
415
419
unregister_mods(MOD_BIT(KC_LALT)); // レイヤータップキーの場合、ここでは ` layer_off(_MY_LAYER) ` を使います
416
420
break;
417
- case DOUBLE_SINGLE_TAP :
421
+ case TD_DOUBLE_SINGLE_TAP :
418
422
unregister_code16(KC_LPRN);
419
423
}
420
424
}
@@ -431,20 +435,22 @@ qk_tap_dance_action_t tap_dance_actions[] = {
431
435
432
436
タップダンスは、MO(layer) と TG(layer) 機能を模倣することにも使用できます。この例では、1回タップすると `KC_QUOT` 、1回押してそのまま押し続けたら `MO(_MY_LAYER)` 、2回タップしたときは `TG(_MY_LAYER)` として機能するキーを設定します。
433
437
434
- 最初のステップは、あなたの `keymap.c` ファイルの最初のあたりに以下のコードを追加します 。
438
+ 最初のステップは、あなたの `keymap.c` ファイルの最初のあたりに以下のコードを追加することです 。
435
439
436
440
```c
441
+ // 必要な数のタップダンス状態のタイプを定義します
442
+ typedef enum {
443
+ TD_NONE,
444
+ TD_UNKNOWN,
445
+ TD_SINGLE_TAP,
446
+ TD_SINGLE_HOLD,
447
+ TD_DOUBLE_TAP
448
+ } td_state_t;
449
+
437
450
typedef struct {
438
451
bool is_press_action;
439
- uint8_t state;
440
- } tap;
441
-
442
- // 必要な数のタップダンス状態のタイプを定義します
443
- enum {
444
- SINGLE_TAP = 1,
445
- SINGLE_HOLD,
446
- DOUBLE_TAP
447
- };
452
+ td_state_t state;
453
+ } td_tap_t;
448
454
449
455
enum {
450
456
QUOT_LAYR, // カスタムタップダンスキー。他のタップダンスキーはこの列挙型に追加します
@@ -453,7 +459,7 @@ enum {
453
459
// タップダンスキーで使われる関数を宣言します
454
460
455
461
// 全てのタップダンスに関連する関数
456
- uint8_t cur_dance(qk_tap_dance_state_t *state);
462
+ td_state_t cur_dance(qk_tap_dance_state_t *state);
457
463
458
464
// 個別のタップダンスに関連する関数
459
465
void ql_finished(qk_tap_dance_state_t *state, void *user_data);
@@ -464,31 +470,31 @@ void ql_reset(qk_tap_dance_state_t *state, void *user_data);
464
470
465
471
``` c
466
472
// 現在のタップダンスの状態を決定します
467
- uint8_t cur_dance (qk_tap_dance_state_t * state) {
473
+ td_state_t cur_dance (qk_tap_dance_state_t * state) {
468
474
if (state->count == 1) {
469
- if (!state->pressed) return SINGLE_TAP ;
470
- else return SINGLE_HOLD ;
471
- } else if (state->count == 2) return DOUBLE_TAP ;
472
- else return 8 ;
475
+ if (!state->pressed) return TD_SINGLE_TAP ;
476
+ else return TD_SINGLE_HOLD ;
477
+ } else if (state->count == 2) return TD_DOUBLE_TAP ;
478
+ else return TD_UNKNOWN ;
473
479
}
474
480
475
481
// この例のタップダンスキーに関連付けられた "tap" 構造体を初期化します
476
- static tap ql_tap_state = {
482
+ static td_tap_t ql_tap_state = {
477
483
.is_press_action = true,
478
- .state = 0
484
+ .state = TD_NONE
479
485
};
480
486
481
487
// タップダンスキーの動作をコントロールする関数
482
488
void ql_finished(qk_tap_dance_state_t * state, void * user_data) {
483
489
ql_tap_state.state = cur_dance(state);
484
490
switch (ql_tap_state.state) {
485
- case SINGLE_TAP :
491
+ case TD_SINGLE_TAP :
486
492
tap_code(KC_QUOT);
487
493
break;
488
- case SINGLE_HOLD :
494
+ case TD_SINGLE_HOLD :
489
495
layer_on(_ MY_LAYER);
490
496
break;
491
- case DOUBLE_TAP :
497
+ case TD_DOUBLE_TAP :
492
498
// レイヤーが既にセットされているか確認します
493
499
if (layer_state_is(_ MY_LAYER)) {
494
500
// レイヤーが既にセットされていたら、オフにします。
@@ -503,10 +509,10 @@ void ql_finished(qk_tap_dance_state_t *state, void *user_data) {
503
509
504
510
void ql_reset(qk_tap_dance_state_t * state, void * user_data) {
505
511
// キーを押し続けていて今離したら、レイヤーをオフに切り替えます。
506
- if (ql_tap_state.state == SINGLE_HOLD ) {
512
+ if (ql_tap_state.state == TD_SINGLE_HOLD ) {
507
513
layer_off(_ MY_LAYER);
508
514
}
509
- ql_tap_state.state = 0 ;
515
+ ql_tap_state.state = TD_NONE ;
510
516
}
511
517
512
518
// タップダンスキーを機能に関連付けます
@@ -519,7 +525,7 @@ qk_tap_dance_action_t tap_dance_actions[] = {
519
525
520
526
`cur_dance()` と `ql_tap_state` の使い方は、上の例と似ています。
521
527
522
- `ql_finished` 関数における `case:SINGLE_TAP ` は、上の例と似ています。`SINGLE_HOLD ` の case では、`ql_reset()` と連動してタップダンスキーを押している間 `_MY_LAYER` に切り替わり、キーを離した時に `_MY_LAYER` から離れます。これは、`MO(_MY_LAYER)` に似ています。`DOUBLE_TAP ` の case では、`_MY_LAYER` がアクティブレイヤーかどうかを確認することによって動きます。そして、その結果に基づいてレイヤーのオン・オフをトグルします。これは `TG(_MY_LAYER)` に似ています。
528
+ `ql_finished` 関数における `case: TD_SINGLE_TAP ` は、上の例と似ています。`TD_SINGLE_HOLD ` の case では、`ql_reset()` と連動してタップダンスキーを押している間 `_MY_LAYER` に切り替わり、キーを離した時に `_MY_LAYER` から離れます。これは、`MO(_MY_LAYER)` に似ています。`TD_DOUBLE_TAP ` の case では、`_MY_LAYER` がアクティブレイヤーかどうかを確認することによって動きます。そして、その結果に基づいてレイヤーのオン・オフをトグルします。これは `TG(_MY_LAYER)` に似ています。
523
529
524
530
`tap_dance_actions[]` は、上の例に似ています。 `ACTION_TAP_DANCE_FN_ADVANCED()` の代わりに `ACTION_TAP_DANCE_FN_ADVANCED_TIME()` を使ったことに注意してください。
525
531
この理由は、私は、非タップダンスキーを使うにあたり `TAPPING_TERM` が短い(175ミリ秒以内)方が好きなのですが、タップダンスのアクションを確実に完了させるには短すぎるとわかったからです——そのため、ここでは時間を275ミリ秒に増やしています。
0 commit comments