CTRL配列 - Ver.2.1

## はじめに
こんにちは、Ctrl です。

https://qiita.com/hiyoctrl/items/00d5bf0b4b4c2e2fb132

https://zenn.dev/ctrl/articles/44564a3fe5fdc2


今回は仕事をする中で、微調整したCTRL配列のマイナーアップデートになります。

<details><summary>keymap.c</summary>

```

#include QMK_KEYBOARD_H
enum layer_number {
    _BASE = 0,_MOD1,_MOD2,_MOD3,_NUM4,_AAA5,_ENG6,_KKK7,
};
enum custom_keycodes {
    LSHB = SAFE_RANGE,
    LSHC,
    LSEC,
    PRN,
    BRC,
    TAE,
    KEY,
    GYOC,
    GYOV,
    LBS,
    CAA,
    CAC,
    CAV,
    CCC,
    CCV,
    PPRN,
};
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    switch (keycode) {
    case LSHB:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_TAP(X_END) SS_LSFT(SS_TAP(X_HOME)) SS_LCTL("b"));
        } else {
        }
        break;
    case LSHC:
        if (record->event.pressed) {
        SEND_STRING(SS_LSFT(SS_TAP(X_HOME)) SS_LCTL("c"));
        } else {
        }
        break;
    case LSEC:
        if (record->event.pressed) {
        SEND_STRING(SS_LSFT(SS_TAP(X_END)) SS_LCTL("c"));
        } else {
        }
        break;
    case PPRN:
        if (record->event.pressed) {
        SEND_STRING(SS_LCTL("x") SS_DELAY(100) "(" SS_DELAY(100) SS_LCTL("v") SS_DELAY(100) ")");
        } else {
        }
        break;
    case PRN:
        if (record->event.pressed) {
        SEND_STRING("()");
        } else {
        }
        break;
    case BRC:
        if (record->event.pressed) {
        SEND_STRING("[]");
        } else {
        }
        break;
    case TAE:
        if (record->event.pressed) {
        SEND_STRING(SS_LCTL("t") SS_DELAY(1200) SS_TAP(X_TAB) SS_TAP(X_ENT));
        } else {
        }
        break;
    case KEY:
        if (record->event.pressed) {
        SEND_STRING(SS_LCTL("c") SS_TAP(X_ESC) "_");
        } else {
        }
        break;
    case GYOC:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_TAP(X_END) SS_LSFT(SS_TAP(X_HOME)) SS_LCTL("c"));
        } else {
        }
        break;
    case GYOV:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_TAP(X_END) SS_LSFT(SS_TAP(X_HOME)) SS_LCTL("v"));
        } else {
        }
        break;
    case LBS:
        if (record->event.pressed) {
        SEND_STRING("l" SS_TAP(X_BSPC));
        } else {
        }
        break;
    case CAA:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_LCTL("a"));
        } else {
        }
        break;
    case CAC:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_LCTL("a") SS_LCTL("c"));
        } else {
        }
        break;
    case CAV:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_LCTL("a") SS_LCTL("v"));
        } else {
        }
    case CCC:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_TAP(X_BTN1) SS_LCTL("c"));
        } else {
        }
    case CCV:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_TAP(X_BTN1) SS_LCTL("v"));
        } else {
        }
        break;
    }
    return true;
};
enum {
    TD_A,TD_B,TD_C,TD_D,TD_E,TD_F,TD_G,TD_H,TD_I,TD_J,TD_K,TD_L,TD_M,
    TD_N,TD_O,TD_P,TD_Q,TD_R,TD_S,TD_T,TD_U,TD_V,TD_W,TD_X,TD_Y,TD_Z,
    TD_VVV,
    TD_CCC,
    TD_HSH,
    TD_ESE,
    TD_ZAY,
    TD_HAF,
    TD_AAF,
    TD_CAL,
    TD_SAR,
    TD_HAC,
    TD_2CA,
    TD_3CA,
    TD_0CA,
    TD_WAT,
    TD_EAU,
    TD_QAD,
    TD_CAX,
    TD_CAA,
    TD_LPA,
    TD_RPA,
    TD_LBC,
    TD_RBC,
};
tap_dance_action_t tap_dance_actions[] = {
    [TD_A] = ACTION_TAP_DANCE_DOUBLE(KC_A, LSFT(KC_A)),
    [TD_B] = ACTION_TAP_DANCE_DOUBLE(KC_B, LSFT(KC_B)),
    [TD_C] = ACTION_TAP_DANCE_DOUBLE(KC_C, LSFT(KC_C)),
    [TD_D] = ACTION_TAP_DANCE_DOUBLE(KC_D, LSFT(KC_D)),
    [TD_E] = ACTION_TAP_DANCE_DOUBLE(KC_E, LSFT(KC_E)),
    [TD_F] = ACTION_TAP_DANCE_DOUBLE(KC_F, LSFT(KC_F)),
    [TD_G] = ACTION_TAP_DANCE_DOUBLE(KC_G, LSFT(KC_G)),
    [TD_H] = ACTION_TAP_DANCE_DOUBLE(KC_H, LSFT(KC_H)),
    [TD_I] = ACTION_TAP_DANCE_DOUBLE(KC_I, LSFT(KC_I)),
    [TD_J] = ACTION_TAP_DANCE_DOUBLE(KC_J, LSFT(KC_J)),
    [TD_K] = ACTION_TAP_DANCE_DOUBLE(KC_K, LSFT(KC_K)),
    [TD_L] = ACTION_TAP_DANCE_DOUBLE(KC_L, LSFT(KC_L)),
    [TD_M] = ACTION_TAP_DANCE_DOUBLE(KC_M, LSFT(KC_M)),
    [TD_N] = ACTION_TAP_DANCE_DOUBLE(KC_N, LSFT(KC_N)),
    [TD_O] = ACTION_TAP_DANCE_DOUBLE(KC_O, LSFT(KC_O)),
    [TD_P] = ACTION_TAP_DANCE_DOUBLE(KC_P, LSFT(KC_P)),
    [TD_Q] = ACTION_TAP_DANCE_DOUBLE(KC_Q, LSFT(KC_Q)),
    [TD_R] = ACTION_TAP_DANCE_DOUBLE(KC_R, LSFT(KC_R)),
    [TD_S] = ACTION_TAP_DANCE_DOUBLE(KC_S, LSFT(KC_S)),
    [TD_T] = ACTION_TAP_DANCE_DOUBLE(KC_T, LSFT(KC_T)),
    [TD_U] = ACTION_TAP_DANCE_DOUBLE(KC_U, LSFT(KC_U)),
    [TD_V] = ACTION_TAP_DANCE_DOUBLE(KC_V, LSFT(KC_V)),
    [TD_W] = ACTION_TAP_DANCE_DOUBLE(KC_W, LSFT(KC_W)),
    [TD_X] = ACTION_TAP_DANCE_DOUBLE(KC_X, LSFT(KC_X)),
    [TD_Y] = ACTION_TAP_DANCE_DOUBLE(KC_Y, LSFT(KC_Y)),
    [TD_Z] = ACTION_TAP_DANCE_DOUBLE(KC_Z, LSFT(KC_Z)),
    [TD_VVV] = ACTION_TAP_DANCE_DOUBLE(RCS(KC_V),    LCTL(KC_V)),
    [TD_CCC] = ACTION_TAP_DANCE_DOUBLE(LCTL(KC_C),   RCS(KC_C)),
    [TD_HSH] = ACTION_TAP_DANCE_DOUBLE(KC_HOME,      LSFT(KC_HOME)),
    [TD_ESE] = ACTION_TAP_DANCE_DOUBLE(KC_END,       LSFT(KC_END)),
    [TD_ZAY] = ACTION_TAP_DANCE_DOUBLE(LCTL(KC_Z),   LCTL(KC_Y)),
    [TD_HAF] = ACTION_TAP_DANCE_DOUBLE(LCTL(KC_H),   LCTL(KC_F)),
    [TD_AAF] = ACTION_TAP_DANCE_DOUBLE(KC_ASTR,      LGUI(KC_UP)),
    [TD_CAL] = ACTION_TAP_DANCE_DOUBLE(KC_COLN,      LGUI(KC_LEFT)),
    [TD_SAR] = ACTION_TAP_DANCE_DOUBLE(KC_SLSH,      LGUI(KC_RGHT)),
    [TD_HAC] = ACTION_TAP_DANCE_DOUBLE(LCTL(KC_SPC), KC_CAPS),
    [TD_2CA] = ACTION_TAP_DANCE_DOUBLE(KC_2,         LCA(KC_2)),
    [TD_3CA] = ACTION_TAP_DANCE_DOUBLE(KC_3,         LCA(KC_3)),
    [TD_0CA] = ACTION_TAP_DANCE_DOUBLE(KC_0,         LCA(KC_0)),
    [TD_WAT] = ACTION_TAP_DANCE_DOUBLE(LCTL(KC_W),   RCS(KC_T)),
    [TD_EAU] = ACTION_TAP_DANCE_DOUBLE(KC_EXLM,      RCS(KC_PGUP)),
    [TD_QAD] = ACTION_TAP_DANCE_DOUBLE(KC_QUES,      RCS(KC_PGDN)),
    [TD_CAX] = ACTION_TAP_DANCE_DOUBLE(LCTL(KC_C),   LCTL(KC_X)),
    [TD_CAA] = ACTION_TAP_DANCE_DOUBLE(LALT(KC_TAB), LCA(KC_TAB)),
    [TD_LPA] = ACTION_TAP_DANCE_DOUBLE(KC_LPRN,      KC_LABK),
    [TD_RPA] = ACTION_TAP_DANCE_DOUBLE(KC_RPRN,      KC_RABK),
    [TD_LBC] = ACTION_TAP_DANCE_DOUBLE(KC_LBRC,      KC_LABK),
    [TD_RBC] = ACTION_TAP_DANCE_DOUBLE(KC_RBRC,      KC_RABK),
};

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    [_BASE] = LAYOUT(
    LCTL(KC_SPC), LT(7,KC_DOT), LT(3,KC_COMM),KC_UP,        TD(TD_VVV),
    LT(4,KC_ESC), KC_LEFT,      KC_RGHT,      LT(6,KC_BTN1),TD(TD_CCC),
    KC_TAB,       XXXXXXX,      XXXXXXX,      KC_DOWN,      LT(2,KC_SPC),
    XXXXXXX,      XXXXXXX,      KC_DEL,       LT(5,KC_BSPC),LT(1,KC_ENT),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
    [_MOD1] = LAYOUT(
    KC_SCLN,      KC_COLN,      KC_SLSH,      LSFT(KC_UP),  CAA,
    KC_TILD,      LSFT(KC_LEFT),LSFT(KC_RGHT),TD(TD_ZAY),   LCTL(KC_X),
    KC_ASTR,      XXXXXXX,      XXXXXXX,      LSFT(KC_DOWN),TD(TD_HAF),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
    [_MOD2] = LAYOUT(
    KC_QUOT,      KC_EXLM,      KC_QUES,      KC_HOME,      LSFT(KC_DEL),
    KC_HASH,      LSFT(KC_HOME),LSFT(KC_END), TD(TD_WAT),   LCTL(KC_S),
    KC_DQUO,      XXXXXXX,      XXXXXXX,      KC_END,       XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      LSHB,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
    [_MOD3] = LAYOUT(
    XXXXXXX,      KC_PLUS,      XXXXXXX,      KC_CAPS,      KC_CIRC,
    KC_EQL,       XXXXXXX,      XXXXXXX,      RCS(KC_S),    KC_BSLS,
    KC_AT,        XXXXXXX,      XXXXXXX,      GYOV,         GYOC,       
    XXXXXXX,      XXXXXXX,      XXXXXXX,      CAV,          CAC,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
    [_NUM4] = LAYOUT(
    XXXXXXX,      KC_1,         TD(TD_2CA),   TD(TD_3CA),   KC_4,
    XXXXXXX,      KC_5,         KC_6,         KC_7,         KC_8,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      KC_9,         TD(TD_0CA),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      KC_MINS,      KC_UNDS,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
    [_AAA5] = LAYOUT(
    TD(TD_L),     TD(TD_O),     TD(TD_E),     TD(TD_Y),     TD(TD_W),
    TD(TD_A),     TD(TD_J),     TD(TD_C),     TD(TD_I),     TD(TD_V),
    TD(TD_Q),     XXXXXXX,      XXXXXXX,      TD(TD_U),     TD(TD_F),
    XXXXXXX,      XXXXXXX,      TD(TD_X),     XXXXXXX,      XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
    [_ENG6] = LAYOUT(
    TD(TD_R),     TD(TD_S),     TD(TD_T),     XXXXXXX,      XXXXXXX,
    TD(TD_K),     TD(TD_Z),     TD(TD_D),     XXXXXXX,      XXXXXXX,
    TD(TD_G),     XXXXXXX,      XXXXXXX,      TD(TD_N),     TD(TD_B),
    XXXXXXX,      XXXXXXX,      TD(TD_P),     TD(TD_M),     TD(TD_H),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
    [_KKK7] = LAYOUT(
    XXXXXXX,      XXXXXXX,      KC_GRV,       KC_PERC,      KC_AMPR,
    LGUI(KC_LEFT),XXXXXXX,      XXXXXXX,      LGUI(KC_RGHT),XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      TD(TD_LBC),   TD(TD_RBC),
    XXXXXXX,      XXXXXXX,      KC_DLR,       TD(TD_LPA),   TD(TD_RPA),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
};

```

</details>

以上が今回の全体のサンプルコードになります。

マクロやタップダンスについては、キーボードレイアウトに組み込まれていないものもあります。また、想定していたような挙動をしないものについても、微調整中のため記載しておりますので、サンプルコードの取り扱いについては自己責任でお願いします。

## マクロ (一部抜粋)

```

    case GYOC:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_TAP(X_END) SS_LSFT(SS_TAP(X_HOME)) SS_LCTL("c"));
        } else {
        }
        break;
    case GYOV:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_TAP(X_END) SS_LSFT(SS_TAP(X_HOME)) SS_LCTL("v"));
        } else {
        }
        break;
    case CAA:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_LCTL("a"));
        } else {
        }
        break;
    case CAC:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_LCTL("a") SS_LCTL("c"));
        } else {
        }
        break;
    case CAV:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_LCTL("a") SS_LCTL("v"));
        } else {
        }

```

トリプルクリックをして、行を選択するような作業が少々面倒、もしくはマウスの左クリックを押したまま、該当する箇所を選択するという作業が右手に負担があると感じ、1タップでクリック、行の指定と選択、そしてコピーと貼り付けを行うマクロを作りました。 

GYOCとGYOVがそれに該当します。

同様に、1タップでクリック、ドキュメントや入力欄に含まれる文字列の全てを選択、そしてコピーと貼り付けを行うマクロを作りました。 

CACとCAVがそれに該当します。

CAAも同じようなマクロであり、マウスカーソルを合わせた場所をクリック、全てを選択するという形です。 

## キー配列：キーボードレイアウト (一部抜粋)

```

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    [_BASE] = LAYOUT(
    LCTL(KC_SPC), LT(7,KC_DOT), LT(3,KC_COMM),KC_UP,        TD(TD_VVV),
    LT(4,KC_ESC), KC_LEFT,      KC_RGHT,      LT(6,KC_BTN1),TD(TD_CCC),
    KC_TAB,       XXXXXXX,      XXXXXXX,      KC_DOWN,      LT(2,KC_SPC),
    XXXXXXX,      XXXXXXX,      KC_DEL,       LT(5,KC_BSPC),LT(1,KC_ENT),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
    [_MOD1] = LAYOUT(
    KC_SCLN,      KC_COLN,      KC_SLSH,      LSFT(KC_UP),  CAA,
    KC_TILD,      LSFT(KC_LEFT),LSFT(KC_RGHT),TD(TD_ZAY),   LCTL(KC_X),
    KC_ASTR,      XXXXXXX,      XXXXXXX,      LSFT(KC_DOWN),TD(TD_HAF),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
    [_MOD2] = LAYOUT(
    KC_QUOT,      KC_EXLM,      KC_QUES,      KC_HOME,      LSFT(KC_DEL),
    KC_HASH,      LSFT(KC_HOME),LSFT(KC_END), TD(TD_WAT),   LCTL(KC_S),
    KC_DQUO,      XXXXXXX,      XXXXXXX,      KC_END,       XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      LSHB,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
    [_MOD3] = LAYOUT(
    XXXXXXX,      KC_PLUS,      XXXXXXX,      KC_CAPS,      KC_CIRC,
    KC_EQL,       XXXXXXX,      XXXXXXX,      RCS(KC_S),    KC_BSLS,
    KC_AT,        XXXXXXX,      XXXXXXX,      GYOV,         GYOC,       
    XXXXXXX,      XXXXXXX,      XXXXXXX,      CAV,          CAC,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
    [_NUM4] = LAYOUT(
    XXXXXXX,      KC_1,         TD(TD_2CA),   TD(TD_3CA),   KC_4,
    XXXXXXX,      KC_5,         KC_6,         KC_7,         KC_8,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      KC_9,         TD(TD_0CA),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      KC_MINS,      KC_UNDS,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
    [_AAA5] = LAYOUT(
    TD(TD_L),     TD(TD_O),     TD(TD_E),     TD(TD_Y),     TD(TD_W),
    TD(TD_A),     TD(TD_J),     TD(TD_C),     TD(TD_I),     TD(TD_V),
    TD(TD_Q),     XXXXXXX,      XXXXXXX,      TD(TD_U),     TD(TD_F),
    XXXXXXX,      XXXXXXX,      TD(TD_X),     XXXXXXX,      XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
    [_ENG6] = LAYOUT(
    TD(TD_R),     TD(TD_S),     TD(TD_T),     XXXXXXX,      XXXXXXX,
    TD(TD_K),     TD(TD_Z),     TD(TD_D),     XXXXXXX,      XXXXXXX,
    TD(TD_G),     XXXXXXX,      XXXXXXX,      TD(TD_N),     TD(TD_B),
    XXXXXXX,      XXXXXXX,      TD(TD_P),     TD(TD_M),     TD(TD_H),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
    [_KKK7] = LAYOUT(
    XXXXXXX,      XXXXXXX,      KC_GRV,       KC_PERC,      KC_AMPR,
    LGUI(KC_LEFT),XXXXXXX,      XXXXXXX,      LGUI(KC_RGHT),XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      TD(TD_LBC),   TD(TD_RBC),
    XXXXXXX,      XXXXXXX,      KC_DLR,       TD(TD_LPA),   TD(TD_RPA),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX),
};

```

新しく作ったマクロは中指のレイヤーでタップするようにしました。ホームポジションから指を外さないまま、1タップでコピー&ペーストができるようなイメージです。

またタップダンスの一部が、記号の入力を連続して使いたい時に誤作動することがあるので外しました。

その他、 TD(TD_HAF)、KC_HOME、KC_ENDなど、想像していたよりも使用するキーを押しやすい位置に変更してあります。

薬指のレイヤーで人差し指と小指をウィンドウ移動に設定を変更、薬指と人差し指でウィンドウを右に、薬指と小指でウィンドウを左に移動することができます。

ウィンドウの最大化については、ウィンドウごとの最大化ボタンを押した方が早いと思ったので外しました。

## まとめと告知

主観的なものになりますが「タップしにくいというストレス」を感じた時に、メモをしておくと、さらに最適化されたキーボード配列が構築しやすいと思いました。

また、タップダンスについても、思ったよりも連打する記号があったので、自分の癖をメモしながら、微調整した方が使いやすいとも考えています。

その他、HOMEやENDが編集作業やWeb ページの閲覧時に想像していたよりも使いやすいキーであることに気づいたのも大きな発見です。同時に、HOMEやENDを基軸としたマクロで、1タップで行やすべてを選択、コピー&ペーストをその箇所ごとに行えるようになり、「マウスの左クリックを固定したまま選択をする」という負荷から解放されたので、心なしか右手の痛みが入ったように感じます。

仕事については、手元の案件がかなり増えてきましたが、ご相談いただければ執筆案件などのお仕事を承ることも可能です。コミュニケーションする中で一緒に仕事をしたい、文章作成したいなどのお気持ちがあれば、遠慮なくご相談ください！

最後までお読みいただきありがとうございました。

https://crowdworks.jp/public/employees/1089210

https://www.lancers.jp/profile/Ctrl

https://coconala.com/users/448062