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

推荐订阅源

美团技术团队
P
Privacy International News Feed
P
Proofpoint News Feed
Security Archives - TechRepublic
Security Archives - TechRepublic
C
CXSECURITY Database RSS Feed - CXSecurity.com
Know Your Adversary
Know Your Adversary
Security Latest
Security Latest
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Attack and Defense Labs
Attack and Defense Labs
NISL@THU
NISL@THU
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
W
WeLiveSecurity
GbyAI
GbyAI
N
News and Events Feed by Topic
N
News | PayPal Newsroom
Y
Y Combinator Blog
C
CERT Recently Published Vulnerability Notes
N
Netflix TechBlog - Medium
S
Security Affairs
Spread Privacy
Spread Privacy
罗磊的独立博客
腾讯CDC
MyScale Blog
MyScale Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
L
LINUX DO - 热门话题
The Cloudflare Blog
L
LangChain Blog
博客园_首页
H
Hacker News: Front Page
宝玉的分享
宝玉的分享
Martin Fowler
Martin Fowler
博客园 - 聂微东
SecWiki News
SecWiki News
A
Arctic Wolf
爱范儿
爱范儿
Google Online Security Blog
Google Online Security Blog
T
Threat Research - Cisco Blogs
Hacker News - Newest:
Hacker News - Newest: "LLM"
有赞技术团队
有赞技术团队
The GitHub Blog
The GitHub Blog
Cyberwarzone
Cyberwarzone
博客园 - 叶小钗
V
Visual Studio Blog
V
V2EX
T
Tailwind CSS Blog
Project Zero
Project Zero
T
The Blog of Author Tim Ferriss
F
Fortinet All Blogs
MongoDB | Blog
MongoDB | Blog
D
Docker

Dvel's Blog

Rime 全拼双拼混输 CHD 油猴脚本:每日签到自动答题 Rime 配置:雾凇拼音 Hammerspoon 自动切换输入法 修复 Hugo 本地图片的累计布局偏移(CLS)问题 macOS 修改 Emacs 键位为 Vim 键位 Surge 配置 汉字的混乱 Netflix 中英双语字幕的好办法 优化 Rime 英文输入体验 判断字符是否为简体字或繁体字 Cloudflare 转入域名提示「出现了问题。请重试转移此域。尚未向您收费。」 图片压缩:Squoosh、TinyPNG、ImageOptim、WebP macOS grep + sed 批量替换多个文件的内容 在 macOS 根目录创建文件夹 博客图床小妙招 折腾 Hugo & PaperMod 主题 利用 Cloudflare Workers 进行批量 301 重定向 将博客部署在 Cloudflare Pages Alfred File Navigation(文件导航器)详解 在 Hugo Goldmark Markdown 中设置以新标签打开链接 日期与时间(UTC、GMT、时间戳、时区) 让 Alfred 以新标签的方式打开 Finder 用 git filter-branch 给 Git 仓库瘦身 qBittorrent 设置教程 联通光猫破解+桥接记录 配置 Mac 终端走代理 Steam for Mac 中文游戏推荐 我的 Mac 软件/工具列表 《Flask Web 开发》笔记 用 sleepwatcher 让 Mac 在睡眠及唤醒时自动执行一些脚本 解决 pyenv 导致的 brew warning 《SQL 必知必会》笔记 Git 自总结 Python 异步 IO 笔记 再见,双点医院! 用 CloudXNS 解决 CNAME 与 MX 记录冲突 你好,Hugo! 为 Mac 打造 zsh command line 环境 新 Mac 新装修 秦皇岛暑期自驾的烦恼 苹果公司开发者账号申请流程 UIScrollView 中使用 Masonry 解决 CocoaPods 的类库 import 没有提示 iOS 使用 CocoaPods 的快速回顾 GitBook 简单生成本地静态 HTML 的方法 你好, Hexo! About
macOS 利用 Karabiner 修改 Emacs 键位为 Vim 键位
Dvel · 2022-11-25 · via Dvel's Blog

上一篇博文用修改 ~/Library/KeyBindings/DefaultKeyBinding.dict 的方法修改按键绑定,但很多地方依然无法响应新的键位设置,体验比较割裂,于是换到 Karabiner

实现方式的区别

DefaultKeyBinding

DefaultKeyBinding.dict 中,用 Ctrl+h 来向左移动,macOS 是通过这样实现的:

"^h" = "moveBackward:";

如果想继续实现 Shift+left(向左移动时选中文本)这个功能,还得需要调用另一个方法:

"^H" = "moveBackwardAndModifySelection:";

苹果原生的方式是直接作用的,比如删除到行首(Ctrl + u)就等于一步操作:直接删除到行首。

Karabiner

Karabiner 要实现删除到行首,它是先通过 Command + Shift + left 来选中光标之前所有的文本,再按下删除键,这样的方式来实现的。

影响可能是有的,比如终端上无法响应,如果自己定义了一个 Ctrl + u,反而还覆盖了其本身正常的功能,不过可以屏蔽掉不需要的 App。

另外无须单独实现带选区的那种,因为 Ctrl+h 已经被映射为左箭头了,自己再加上 Shift 就可以了。

Karabiner 还可以实现更多的功能,比如作者直接写了个全局 Vim 映射,还可以启动 App,设置只限定特定设备、特定 App 等等,功能着实强大,还开源免费。

简单使用

  • Simple Modifications,可以简单映射,比如 CapsLock → Control
  • Complex Modifications,可以引用别人已经写好了的规则。
    • 或者打开 ~/.config/karabiner/assets/complex_modifications 增加自己的规则。
  • Devices,选择要应用到的设备,比如内置键盘。
  • Profiles,定义多套方案,按需选择。

官方文档:https://karabiner-elements.pqrs.org/docs/

社区分享:https://ke-complex-modifications.pqrs.org/

建议查看官方文档熟悉一点小例子,然后下载别人实现类似的功能的 JSON 代码来参考。

文档最下面有个 External JSON generators,比如用这个 Karabiner Complex Modification 可以自动生成 JSON,不过简单的映射还是直接写 JSON 方便。

我的键位设置

原始的 Emacs-like 键位:

Ctrl + ...
a 移动到行首
e 移动到行尾
b 左
f 右
p 上
n 下
h 往左删除一个
d 往右删除一个
w 往左删除单词
u 往左删除到行首
k 往右删除到行尾

自定义的的键位:

Ctrl + ...
a 移动到行首
e 移动到行尾
h 左
l 右
k 上
j 下
o 插入一行
s 往左删除一个
d 往右删除一个
u 往左删除到行首
i 往右删除到行尾
w 往左删除单词

pnbf 仍然可以使用,没有冲突。

a e 不进行任何改动,我还没有发现有不支持的地方。

w u 的功能虽然和上面一样,但有些地方比如 Typora 就不支持,自己实现一遍确保全局有效。

代码

  • (1) CapsLock 短按为 Esc,组合为 Control
  • (2) Ctrl + hjkl 移动光标,排除 JetBrains
    • 上下左右修改为 hjkl,与原来的 pnbf 不冲突,仍然可以使用;
    • 排除 JetBrains,IDEA 自己单独实现普通模式和插入模式不同的行为。
  • (3) Ctrl + aeosduiw,排除 JetBrains 和终端
    • ae 不改动,wu 重新实现了一遍;
    • o 和 Vim 的功能类似,在本行的任何位置直接新建一行并切换过去;
    • 增加了 s、i 两个键位在原来的 d、u 旁边,左边的往左删,右边的往右删,很好记忆;
    • 排除 JetBrains 和终端。
  • (4) Option + [Shift] + hjkl
    • 可以用 Option [+ Shift] + Ctrl + h/l,但按键太多,改成直接按 h/l 也生效;
    • Option + j/k 用于 VSCode 默认快捷键,上下移动此行;
    • Option + Shift + j/k 用于 VSCode 默认快捷键,复制一行;

将代码保存到 ~/.config/karabiner/assets/complex_modifications

因为这个 issue#2774 没有解决,还不能全局限定或屏蔽某 App,代码像面条一样,frontmost_application_unless 相关配置每次修改时都需要同时改动多处地方。

{
  "title": "Dvel's hjkl",
  "rules": [
    {
      "description": "(1) CapsLock 短按为 Esc,组合为 Control",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "caps_lock",
            "modifiers": {
              "optional": [
                "any"
              ]
            }
          },
          "to": [
            {
              "key_code": "left_control",
              "lazy": true
            }
          ],
          "to_if_alone": [
            {
              "key_code": "escape"
            }
          ]
        }
      ]
    },
    {
      "description": "(2) Ctrl + hjkl 移动光标,排除 JetBrains",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "h",
            "modifiers": {
              "mandatory": [
                "left_control"
              ],
              "optional": [
                "any"
              ]
            }
          },
          "to": [
            {
              "key_code": "left_arrow"
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_unless",
              "bundle_identifiers": [
                "jetbrains"
              ]
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "j",
            "modifiers": {
              "mandatory": [
                "left_control"
              ],
              "optional": [
                "any"
              ]
            }
          },
          "to": [
            {
              "key_code": "down_arrow"
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_unless",
              "bundle_identifiers": [
                "jetbrains"
              ]
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "k",
            "modifiers": {
              "mandatory": [
                "left_control"
              ],
              "optional": [
                "any"
              ]
            }
          },
          "to": [
            {
              "key_code": "up_arrow"
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_unless",
              "bundle_identifiers": [
                "jetbrains"
              ]
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "l",
            "modifiers": {
              "mandatory": [
                "left_control"
              ],
              "optional": [
                "any"
              ]
            }
          },
          "to": [
            {
              "key_code": "right_arrow"
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_unless",
              "bundle_identifiers": [
                "jetbrains"
              ]
            }
          ]
        }
      ]
    },
    {
      "description": "(3) Ctrl + aeosduiw,排除 JetBrains 和终端",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "o",
            "modifiers": {
              "mandatory": [
                "left_control"
              ]
            }
          },
          "to": [
            {
              "key_code": "right_arrow",
              "modifiers": [
                "left_command"
              ]
            },
            {
              "key_code": "return_or_enter"
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_unless",
              "bundle_identifiers": [
                "jetbrains",
                "Terminal",
                "iterm",
                "Warp"
              ]
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "s",
            "modifiers": {
              "mandatory": [
                "left_control"
              ]
            }
          },
          "to": [
            {
              "key_code": "delete_or_backspace"
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_unless",
              "bundle_identifiers": [
                "jetbrains",
                "Terminal",
                "iterm",
                "Warp"
              ]
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "d",
            "modifiers": {
              "mandatory": [
                "left_control"
              ]
            }
          },
          "to": [
            {
              "key_code": "delete_forward"
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_unless",
              "bundle_identifiers": [
                "jetbrains",
                "Terminal",
                "iterm",
                "Warp"
              ]
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "u",
            "modifiers": {
              "mandatory": [
                "left_control"
              ]
            }
          },
          "to": [
            {
              "key_code": "left_arrow",
              "modifiers": [
                "left_command",
                "left_shift"
              ]
            },
            {
              "key_code": "delete_or_backspace"
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_unless",
              "bundle_identifiers": [
                "jetbrains",
                "Terminal",
                "iterm",
                "Warp"
              ]
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "i",
            "modifiers": {
              "mandatory": [
                "left_control"
              ]
            }
          },
          "to": [
            {
              "key_code": "right_arrow",
              "modifiers": [
                "left_command",
                "left_shift"
              ]
            },
            {
              "key_code": "delete_forward"
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_unless",
              "bundle_identifiers": [
                "jetbrains",
                "Terminal",
                "iterm",
                "Warp"
              ]
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "w",
            "modifiers": {
              "mandatory": [
                "left_control"
              ]
            }
          },
          "to": [
            {
              "key_code": "left_arrow",
              "modifiers": [
                "option",
                "shift"
              ]
            },
            {
              "key_code": "delete_or_backspace"
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_unless",
              "bundle_identifiers": [
                "jetbrains",
                "Terminal",
                "iterm",
                "Warp"
              ]
            }
          ]
        }
      ]
    },
    {
      "description": "(4) Option [+ Shift] + hjkl",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "h",
            "modifiers": {
              "mandatory": [
                "option"
              ],
              "optional": [
                "shift"
              ]
            }
          },
          "to": [
            {
              "key_code": "left_arrow",
              "modifiers": [
                "option"
              ]
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "j",
            "modifiers": {
              "mandatory": [
                "option"
              ],
              "optional": [
                "shift"
              ]
            }
          },
          "to": [
            {
              "key_code": "down_arrow",
              "modifiers": [
                "option"
              ]
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "k",
            "modifiers": {
              "mandatory": [
                "option"
              ],
              "optional": [
                "shift"
              ]
            }
          },
          "to": [
            {
              "key_code": "up_arrow",
              "modifiers": [
                "option"
              ]
            }
          ]
        },
        {
          "type": "basic",
          "from": {
            "key_code": "l",
            "modifiers": {
              "mandatory": [
                "option"
              ],
              "optional": [
                "shift"
              ]
            }
          },
          "to": [
            {
              "key_code": "right_arrow",
              "modifiers": [
                "option"
              ]
            }
          ]
        }
      ]
    }
  ]
}