惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
Stack Overflow Blog
Stack Overflow Blog
人人都是产品经理
人人都是产品经理
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
Vercel News
Vercel News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Y
Y Combinator Blog
The Cloudflare Blog
Last Week in AI
Last Week in AI
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
V
Visual Studio Blog
博客园 - 三生石上(FineUI控件)
小众软件
小众软件
Google DeepMind News
Google DeepMind News
D
DataBreaches.Net
博客园 - 司徒正美
B
Blog RSS Feed
Microsoft Azure Blog
Microsoft Azure Blog
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
L
LangChain Blog

效率 – Ed_'s Blog

构建网络私有书架,实现听书看书 – yywr's Blog Windows系统下快速输入辅助方案- xlr-space – yywr's Blog 记远程办公体验 – yywr's Blog 当手机丢失,无法及时补卡时 – yywr's Blog 自己编的工作流方案 – yywr's Blog GIT Basic usage – yywr's Blog [记录] 使用AutoIT脚本自动添加远程打印机并配置验证账户 – yywr's Blog 简易个人数据备份方案 – yywr's Blog DTR工作法 – yywr's Blog Keepass 使用记录 – yywr's Blog
macOS 下 xlr-spaceFN 键盘映射方案实现方案 v1 – yywr's Blog
yywr · 2026-06-11 · via 效率 – Ed_'s Blog

macOS 用了差不多一年半,但是一直觉得不得劲,因为在Windows 下,我有一个基于 Autohotkey V1 的键盘映射方案 xlr-sapce 键盘映射方案  for Windows,让我在工作打字时更快的操作光标,移动、选择、编辑,以空格为修饰键,加字母区域的按键,手部不需要任何多余的移动,而在macOS 一直没办法实现

以前在使用 Linux 的时候也尝试实现这个映射方案,最接近的方案是使用 XModMap,但最终还差点,找资料实在太难了,而 AI 让我的想法更好的实现了,所以下面是在 macOS 下xlr-sapceFN 映射方案,虽然不够完美,但是也非常接近了

xlr-sapceFN 映射方案简介

xlr-spaceFN 映射方案与其它键盘映射方案最大的不同,以及最大的优点就是,使用空格作为修饰键,在Windows 下,Autohotkey让这个想法完美实现了,目前macOS 下虽然功能实现了,但还是有点遗憾

本配置将空格键改造为一个智能功能层激活键:

  • 轻点空格 → 正常输出空格(无延迟感,一般100-150毫秒内,自己调)
  • 按住空格 → 激活功能层,此时按下特定字母键可执行导航、编辑等快捷操作

快速参考卡片(按键位布局)

q
 
w
Bksp
e
r
Del
t
 
y
PgUp
u
Sel←
i
Sel↑
o
Sel→
p
Page Home
a
Home
s
d
f
g
End
h
←选词
j
←选择
k
↓选择
l
→选择
Enter
行尾 + 换行
 
z
Undo
x
Cut
c
Copy
v
Paste
b
PgDn
n
→选词
m
 
  
Page End
按住空格键时

macOS xlr-sapceFN 映射方案实现核心思路:如何实现“空格当修饰键”

实现方式:使用 Karabiner-Elements+ 配置文件的方式实现

Karabiner 的规则不能直接写 GetKeyState,但可以通过 to_if_held_downto_if_alone 组合实现:

  • 当按下空格并稍后释放(没有按其他键)→ 发送 space(单独空格)。
  • 当按下空格并按住不放时 → 进入“修饰键模式”,此时再按其他键触发自定义动作。

当前必须接受的缺点

Karabiner-Elements 无法实现和 AutoHotkey 完全一致的逻辑,这是两个平台键盘事件处理机制上的本质差异导致的:AutoHotkey 在 Windows 低层 (钩子) 驱动可以直接操控键盘状态,强制将其“角色”转换;而 Karabiner-Elements 在 macOS 受沙盒限制,只能通过“裁决”策略用延迟判断该输出字符还是激活功能,无法做到真正的零延迟使用方法

具体来说就是:在 macOS 下,必须为空格按下进程设置一个延迟时间,比如说 150 毫秒:

  • 在这个时间内:按下并释放空格则正常输出空格 >>> 理想状态
  • 在这个时间内:按下空格和其它键并释放,没有冲突的情况下,输出其它键 >>> 难受状态
  • 在这个时间之后:按下并释放空格没有任何反应 >>> 难受状态
  • 在这个时间之后:按下空格和设定的组合键,实现设定的映射 >>> 理想状态

在上面几种情况中,日常使用其实还是非常容易触发难受状态的,整个工作流程会受到一点影响,相对来说来还是能够接受的 ,最难受的其实是使用删除的时候,很多时候删除操作非常快,但按太快容易进入难受状态,以后再想办法吧

操作指引

  1. 下载并安装Karabiner-Elements后打开,进入Setup ,将所有功能打开,尤其是 Driver Extension
  2. 将下面的 JSON 代码保存为 ~/.config/karabiner/assets/complex_modifications/xlr_spaceFN_modifier.json(如果目录不存在则手动创建)。
  3. 打开 Karabiner-Elements → Complex Modifications → Add predefined rule → xlr-SpaceFN → Enable All
  4. 如果某些快捷键与系统快捷键冲突(如 Ctrl+Space 切换输入法),可以在 Karabiner 的 Simple Modifications 或系统设置中关闭对应组合。
  5. [Base] Hold Spacebar to activate layer (required) 是必须启用的 ,其它的已经分成了移动、选择、编辑三块,按需要开启

方案代码

  1. 基础层(必需) – 按住空格激活功能层(设置变量)
  2. 光标移动层 – 方向键、行首行尾、翻页
  3. 文本选择层 – Shift + 方向、按词选择、选至行首尾
  4. 编辑操作层 – 删除、复制粘贴、撤销、行尾换行

基础层必须启用,其他层可以任意组合启用/禁用。
所有规则共用同一个变量 space_fn_layer,互不冲突。

将下面代码按指引中的第二步保存为 josn 文件

{
    "title": "xlr-SpaceFN-v2",
    "rules": [
        {
            "description": "[Base] Hold Spacebar to activate layer (required)",
            "manipulators": [
                {
                    "description": "Hold Spacebar for Layer (with delay)",
                    "from": {
                        "key_code": "spacebar",
                        "modifiers": { "optional": ["any"] }
                    },
                    "to_if_alone": [{ "key_code": "spacebar" }],
                    "to_if_held_down": [{ "set_variable": { "name": "space_fn_layer", "value": 1 } }],
                    "to_after_key_up": [{ "set_variable": { "name": "space_fn_layer", "value": 0 } }],
                    "parameters": {
                        "basic.to_if_alone_timeout_milliseconds": 110,
                        "basic.to_if_held_down_threshold_milliseconds": 111
                    },
                    "type": "basic"
                }
            ]
        },
        {
            "description": "[Block 1] Cursor Movement (e,s,d,f | a,g | y,b)",
            "manipulators": [
                {
                    "from": { "key_code": "e" },
                    "to": [{ "key_code": "up_arrow" }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "s" },
                    "to": [{ "key_code": "left_arrow" }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "d" },
                    "to": [{ "key_code": "down_arrow" }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "f" },
                    "to": [{ "key_code": "right_arrow" }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "a" },
                    "to": [{ "key_code": "left_arrow", "modifiers": ["left_command"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "g" },
                    "to": [{ "key_code": "right_arrow", "modifiers": ["left_command"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "y" },
                    "to": [{ "key_code": "page_up" }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "b" },
                    "to": [{ "key_code": "page_down" }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                }
            ]
        },
        {
            "description": "[Block 2] Text Selection (i,j,k,l | h,n | u,o)",
            "manipulators": [
                {
                    "from": { "key_code": "i" },
                    "to": [{ "key_code": "up_arrow", "modifiers": ["left_shift"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "j" },
                    "to": [{ "key_code": "left_arrow", "modifiers": ["left_shift"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "k" },
                    "to": [{ "key_code": "down_arrow", "modifiers": ["left_shift"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "l" },
                    "to": [{ "key_code": "right_arrow", "modifiers": ["left_shift"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "h" },
                    "to": [{ "key_code": "left_arrow", "modifiers": ["left_shift", "left_option"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "n" },
                    "to": [{ "key_code": "right_arrow", "modifiers": ["left_shift", "left_option"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "u" },
                    "to": [{ "key_code": "left_arrow", "modifiers": ["left_command", "left_shift"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "o" },
                    "to": [{ "key_code": "right_arrow", "modifiers": ["left_command", "left_shift"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                }
            ]
        },
        {
            "description": "[Block 3] Editing (w,r | c,x,v,z | p,/, Enter)",
            "manipulators": [
                {
                    "from": { "key_code": "w" },
                    "to": [{ "key_code": "delete_or_backspace" }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "r" },
                    "to": [{ "key_code": "delete_forward" }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "c" },
                    "to": [{ "key_code": "c", "modifiers": ["left_command"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "x" },
                    "to": [{ "key_code": "x", "modifiers": ["left_command"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "v" },
                    "to": [{ "key_code": "v", "modifiers": ["left_command"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "z" },
                    "to": [{ "key_code": "z", "modifiers": ["left_command"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "p" },
                    "to": [{ "key_code": "up_arrow", "modifiers": ["left_command"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "slash" },
                    "to": [{ "key_code": "down_arrow", "modifiers": ["left_command"] }],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                },
                {
                    "from": { "key_code": "return_or_enter" },
                    "to": [
                        { "key_code": "right_arrow", "modifiers": ["left_command"] },
                        { "key_code": "return_or_enter" }
                    ],
                    "conditions": [{ "name": "space_fn_layer", "type": "variable_if", "value": 1 }],
                    "type": "basic"
                }
            ]
        }
    ]
}