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

推荐订阅源

T
Tenable Blog
Last Week in AI
Last Week in AI
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
H
Help Net Security
F
Fortinet All Blogs
MyScale Blog
MyScale Blog
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 司徒正美
量子位
N
Netflix TechBlog - Medium
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件
Recorded Future
Recorded Future
博客园 - 三生石上(FineUI控件)
Vercel News
Vercel News
aimingoo的专栏
aimingoo的专栏
I
InfoQ
Microsoft Security Blog
Microsoft Security Blog
Scott Helme
Scott Helme
The Last Watchdog
The Last Watchdog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
IT之家
IT之家
AI
AI
WordPress大学
WordPress大学
Security Archives - TechRepublic
Security Archives - TechRepublic
Google Online Security Blog
Google Online Security Blog
U
Unit 42
V2EX - 技术
V2EX - 技术
MongoDB | Blog
MongoDB | Blog
Schneier on Security
Schneier on Security
博客园 - Franky
H
Heimdal Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Jina AI
Jina AI
W
WeLiveSecurity
P
Privacy & Cybersecurity Law Blog
Cloudbric
Cloudbric
B
Blog RSS Feed
N
News | PayPal Newsroom
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
I
Intezer
Hacker News - Newest:
Hacker News - Newest: "LLM"
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园_首页
罗磊的独立博客
H
Hackread – Cybersecurity News, Data Breaches, AI and More
雷峰网
雷峰网

yywr – Ed_'s Blog

给 Debian 开了自动安全更新 – yywr's Blog 移动网络/高延迟网络下 ssh 的替代品 – yywr's Blog H3C NX30PRO 半砖救回记 – yywr's Blog OBS摄像头设置教程:画面形状与绿幕功能详解 – yywr's Blog 走出舒适区的第一步:先做个垃圾出来 – yywr's Blog 视频录制和推流直播工具OBS Studio 的使用 – 基础篇 – yywr's Blog [一个酷酷的软件] Readest 电子书阅读器 – yywr's Blog UPower – 将笔记本电池当成UPS使用 – yywr's Blog 私有音乐服务 Navidrome:部署与Nginx 二级目录反代访问 – yywr's Blog 简单的私有云数据访问工具 – FileBrowser 部署记要 – yywr's Blog 配置评论邮件通知,沮丧的一天 – yywr's Blog 停止想象 – yywr's Blog 关于冥想的一些想法 – yywr's Blog
macOS 下 xlr-spaceFN 键盘映射方案实现方案 v1 – yywr's Blog
yywr · 2026-06-11 · via yywr – 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"
                }
            ]
        }
    ]
}