SpaceFNのすゝめ

キーボードのカスタマイズに興味はありますか? WindowsではAutoHotKeyやChange Key、MacではKarabiner-Elementsといったツールを使って、キーの配置を変更している方も多いのではないでしょうか。

さらに、最近のキーボードにはQMKやVIAといった機能が搭載されているモデルも増えており、これらを活用すれば、プログラム不要で簡単にキーマップを変更することが可能です。

この記事では、今回はそんなキーボードマッピングのカスタマイズの中でも「SpaceFN」というコンセプトについて紹介します。

ハリネズミくん

僕もキーボードはQMK/VIA対応の「Keychron K8 Pro」を使用しており、QMK/VIA機能を使って「SpaceFN」を設定し、好みのキーマップに変更して利用しています!

(追記) 英数かなキーをFnキーとして活用する方法に関しても記事にしています。個人的には以下のやり方のほうがオススメです。

はじめに:SpaceFNとは?

SpaceFN(スペースエフエヌ)は、スペースキーを「キーボードレイヤーの切り替えキー」として活用するコンセプトです。
スペースキーを単体で入力するとスペースの入力として動作しますが、スペースを押しながら他のキーを使うと、「レイヤー」が切り替わり、それらのキーが別の役割を果たすように動作します。

由来について詳しくはわかりませんが、geekhack(https://geekhack.org/index.php?topic=51069.0) というウェブサイトでspiceBarという方が投稿されて話題になったようです。

例えば、スペースを押していないときは通常のキーマップで入力できます。

引用元:https://geekhack.org/index.php?topic=51069.0

スペースを押したままにすると、以下のキーマップに変わります。

引用元:https://geekhack.org/index.php?topic=51069.0

スペースを押したままにしたときのマッピングは、自由にカスタマイズできます。

例えば...

  • スペースキーを押しながら h, j, k, l を押すと矢印キー(左・下・上・右)として動作させる
  • スペースキーを押しながら u を押すと Homeキーとして動作させる
  • スペースキーを押しながら o を押すと Endキーとして動作させる

などと自由に設定することも可能です。
これにより、ホームポジションから手を離さずに、効率的かつ快適にタイピングが可能になります。

なぜSpaceFNを導入すると良いのか?

通常、スペースキーはタイピング中に使用頻度が高い一方で、キーボード上のスペースを大きく占有しています。

スペースキーは、右手でも左手でも、簡単に押すことができるすごくいい位置にあるキーです。
これをスペースの入力だけに使っているのはもったいない、ということで有効活用してあげましょう、というのがSpaceFNの基本的な発想です。単純ながら非常に画期的なアイデアで、実は多くのプログラマーやキーボード愛好家たちから支持されています。

次のようなメリットがあります。

1. ホームポジションを維持して効率アップ

通常、矢印キーやファンクションキーを使うときには、ホームポジションから手を離す必要があります。しかし、SpaceFNを使えば、スペースキーを押しながら近くのキーを操作するだけで、カーソル移動やショートカットが実現できます。

例えば:

  • 矢印キーの代わり
    • H, J, K, Lに「← ↓ ↑ →」を割り当てれば、カーソル移動のために右手を遠くに動かす必要がありません。
  • ページスクロールの操作
    • UとIに「Page Up」と「Page Down」を割り当てることで、スクロールも簡単になります。

これにより、特にプログラミングや文章作成において効率が大幅に向上します。

2. 手首や指への負担軽減

長時間のタイピングやキー操作は、手首や指に大きな負担をかけます。特に、CtrlやAltなどのショートカットキーを頻繁に押す人にとっては、この負担が顕著です。

SpaceFNは、手の移動を最小限に抑える設計になっているため、以下の効果が期待できます。

  • 手首を無理な角度で動かさずに済む
  • 指を伸ばす動作が減り、疲労感を軽減
  • RSI(反復性ストレス障害)のリスクを低減

3. 学習コストが低い

「新しいレイアウトを覚えるのは大変そう」と思うかもしれませんが、SpaceFNの学習コストは比較的低めです。

  • スペースキーを単体で押した場合は、従来通りスペースが入力できるため、従来通りの入力が可能
  • スペースキーという「親しみのあるキー」を軸にしているため、自然と使い方に慣れる

初心者でも無理なく始められる設計です。

4. 複数の環境に対応可能

SpaceFNは、さまざまなOSやソフトウェアツールで実現可能です。

  • macOSならKarabiner-Elements など
  • WindowsならAutoHotKey など
  • 多くのQMK対応キーボードでファームウェア設定

これにより、使うデバイスを選ばずに統一した操作感を実現できます。

ハリネズミくん

僕もMac、Windows、QMK対応キーボードを使った状態など、それぞれを使う環境がありますが、どこでも同じキーバインドで作業できるようにしています。設定は記事の後半で紹介します!60%キーボードや、HHKBなどのキー数の少ないキーボードを使っている方には特にオススメです!

ただし、ゲーム中にはSpaceFNをオススメしない

ゲームなど、スペースを連続入力することでキャラクターを操作する場面ではオススメしません。

SpaceFNを有効化すると、スペースを押し続けても、入力されるスペースは1つです。
「スペースを押し続ける」という操作が必要になることが多いと思いますので、SpaceFnのこの動作は致命的です。
ゲーム中はオフにしておく、などとして運用するとよいと思います。

キーボードのカスタマイズは、もはや難しくない

特別なキーボードが無くても、AutoHotKeyやKarabiner-Elementsといったキーマッピング変更ツールを使用すればすぐにSpaceFnをお試しできます。また、以前と比べてQMK/VIAに対応したキーボードも増えており、キーボードのカスタマイズが驚くほど簡単になりました。

QMKとは?

QMK(Quantum Mechanical Keyboard)ファームウェアは、キーボードの機能を根本から変える強力なオープンソースのソフトウェアです。従来は、キーボードの設定変更には高度なプログラミングスキルが必要でした。しかし、QMKの登場により、誰もが簡単にキーボードをカスタマイズできるようになりました。

VIAを活用した簡単なキーマップ変更

VIAは、QMKファームウェアと連携するソフトウェアです。

VIAのウェブサイトにアクセスすることでキーマッピングを設定することができます。ブラウザ上のGUIからQMK/VIA機能をもつキーボードのキーマップ変更やマクロ登録などの設定ができます。

プログラミングの知識がなくても、直感的な操作でキーボードをカスタマイズできるのが最大の特徴です。

導入方法

QMK/VIAに対応したキーボードをお持ちで、SpaceFNを設定したい場合は、「VIAを利用したSpaceFNの実装方法」を参照ください。

QMK/VIAなしで、キーマッピング変更ツールでSpaceFNを実現したい場合は、OSごとに記載しています。
Windowsの場合は「WindowsPCの場合: AutoHotKeyを利用した実現方法」を参照ください。
Macの場合は、「Macの場合: Karabiner-Elementsを利用した実現方法」を参照ください。

VIAを利用したSpaceFNの実装方法

VIAを利用して実装する例を紹介します。

すでに利用しているキーマップがある場合は事前にバックアップを取っておきましょう!

  1. VIAの設定サイト(https://usevia.app/ )を開き、デバイスを接続します。
  2. 通常入力時の時のレイヤーを選択し、スペースのキーの位置に 「LAYERS」にある 「Space FnX」を選択します。
    Xは、スペースで切り替え先のレイヤー番号にします
  1. スペース切り替え先のレイヤーを選択し、スペースを押しながら入力したときのキーマップを設定します
僕のキーマップ設定例(お好みで変更してください!)

たったこれだけでSpaceFnを実現できます。

WindowsPCの場合: AutoHotKeyを利用した実現方法

AutoHotKeyを利用して、実現できます。

AutoHotKey(https://www.autohotkey.com/)をインストールして、キーマップの変更設定を記載したahkスクリプトを動かすことでキーマップを変更することができます。

以下GitHubにahkスクリプトのサンプルが公開されているので、参考にして実装するとよいかと思います。

  1. https://github.com/lydell/spacefn-win/blob/master/spacefn-win.ahk
  2. https://github.com/OhYee/SpaceFn/blob/master/Spacefn.ahk

参考までに、僕が使用しているahkスクリプトを貼っておきます。上記 2.のサイトのものを少しだけ変えて使用しています。
個人的に使いやすいマッピングにカスタマイズしてしまっているのお好みに応じて変更して使用いただければと思います!

ここをクリックしてahkスクリプト(SpaceFn.ahk)の例を表示
;SpaceFn
#inputlevel,2
$Space::
    SetMouseDelay -1
    Send {Blind}{F24 DownR}
    KeyWait, Space
    Send {Blind}{F24 up}
    ; MsgBox, %A_ThisHotkey%-%A_TimeSinceThisHotkey%
    if(A_ThisHotkey="$Space" and A_TimeSinceThisHotkey<1000)
        Send {Blind}{Space DownR}
    return


#inputlevel,1
F24 & f::Space
F24 & e::Escape
F24 & h::Left
F24 & j::Down
F24 & k::Up
F24 & l::Right
F24 & u::Home
F24 & o::End
F24 & [::PgUp
F24 & ]::PgDn
F24 & n::Backspace
F24 & m::Delete

F24 & 1::F1
F24 & 2::F2
F24 & 3::F3
F24 & 4::F4
F24 & 5::F5
F24 & 6::F6
F24 & 7::F7
F24 & 8::F8
F24 & 9::F9
F24 & 0::F10
F24 & -::F11
F24 & =::F12

;F24 & Enter::^Enter

Macの場合: Karabiner-Elementsを利用した実現方法

Karabiner-Elementsを利用して、実現できます。
Karabiner-Elementsのサイトで公開されているSpaceFNは、なぜかスペースが暴発するなどしてうまく動作しませんでした。(使い方が悪かったのかも…)

ですので、MacBook本体キーボードで自作キーボードのレイヤー機能を再現する方法 という記事を参考に、カスタマイズすることで実現しました。

参考までに、僕が使用しているSpaceFNの設定ファイルを貼っておきます。
個人的に使いやすいマッピングにカスタマイズしてしまっているのお好みに応じて変更して使用いただければと思います!

以下のファイルを ~/.config/karabiner/assets/complex_modifications/SpaceFn.json に配置し、Karabiner-Elements側で有効化します。

ここをクリックして SpaceFn.json の例を表示
{
  "title": "SpaceFn",
  "rules": [
    {
      "description": "SpaceFnLayer",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "spacebar",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "set_variable": {
                "name": "layerSpacebar",
                "value": 1
              }
            }
          ],
          "to_if_alone": [
            {
              "key_code": "spacebar"
            }
          ],
          "to_after_key_up": [
            {
              "set_variable": {
                "name": "layerSpacebar",
                "value": 0
              }
            }
          ]
        }
      ]
    },
    {
      "description": "SpaceFnKeyMapping",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "1",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "f1"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "2",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "f2"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "3",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "f3"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "4",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "f4"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "5",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "f5"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "6",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "f6"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "7",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "f7"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "8",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "f8"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "9",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "f9"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "0",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "f10"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "hyphen",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "f11"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "equal_sign",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "f12"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "u",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "left_arrow",
              "modifiers": "left_command"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "o",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "right_arrow",
              "modifiers": "left_command"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "e",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "escape"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "f",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "spacebar"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "h",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "left_arrow"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "a",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "left_arrow"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "j",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "down_arrow"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "s",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "down_arrow"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "k",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "up_arrow"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "w",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "up_arrow"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "l",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "right_arrow"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "d",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "right_arrow"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "close_bracket",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "page_up"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "backslash",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "page_down"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "n",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "delete_or_backspace"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "m",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "delete_forward"
            }
          ],
          "conditions": [
            {
              "type": "variable_if",
              "name": "layerSpacebar",
              "value": 1
            }
          ]
        }
      ]
    }
  ]
}

ここで紹介したツール以外でも様々なツールで実現可能だと思うので、お好みのツールがあれば調べてみるとよいかと思います!

最後に

SpaceFNは、僕も使い始めてまだ日が浅いのですが、かなり快適に使用できています。

学習コストも低いので、ぜひ試してみてください!

参考

  • B!