commit d982c008467773c8982cc07977d649a2c5198b4b
parent 4076994db6252e79400e4dd5498431d52e938b5b
Author: zeertzjq <zeertzjq@outlook.com>
Date: Mon, 26 Jan 2026 06:58:57 +0800
vim-patch:9.1.2110: filetype: skhd files are not recognized
Problem: filetype: skhd files are not recognized
Solution: Detect .skhdrc and skhdrc as skhd filetype,
include a syntax and filetype plugin, add syntax tests
(Kiyoon Kim)
Add syntax highlighting for skhd (simple hotkey daemon for macOS)
configuration files. Includes filetype detection for skhdrc and
.skhdrc files.
Reference:
- https://github.com/asmvik/skhd
closes: vim/vim#19235
https://github.com/vim/vim/commit/e5f61842b509acea91c63923e60987ad7ae123dd
Co-authored-by: Kiyoon Kim <kiyoon@users.noreply.github.com>
Diffstat:
4 files changed, 160 insertions(+), 0 deletions(-)
diff --git a/runtime/ftplugin/skhd.vim b/runtime/ftplugin/skhd.vim
@@ -0,0 +1,20 @@
+" Vim filetype plugin file
+" Language: skhd(simple hotkey daemon for macOS) configuration file
+" Maintainer: Kiyoon Kim <https://github.com/kiyoon>
+" Last Change: 2026 Jan 23
+
+if exists("b:did_ftplugin")
+ finish
+endif
+let b:did_ftplugin = 1
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+setlocal comments=:# commentstring=#\ %s
+setlocal formatoptions-=t formatoptions+=croql
+
+let b:undo_ftplugin = "setl com< cms< fo<"
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
@@ -1906,6 +1906,8 @@ local filename = {
['.tcshrc'] = detect.tcsh,
['tcsh.login'] = detect.tcsh,
['tcsh.tcshrc'] = detect.tcsh,
+ ['.skhdrc'] = 'skhd',
+ ['skhdrc'] = 'skhd',
['/etc/slp.conf'] = 'slpconf',
['/etc/slp.reg'] = 'slpreg',
['/etc/slp.spi'] = 'slpspi',
diff --git a/runtime/syntax/skhd.vim b/runtime/syntax/skhd.vim
@@ -0,0 +1,137 @@
+" Vim syntax file
+" Language: skhd configuration file
+" Maintainer: Kiyoon Kim <https://github.com/kiyoon>
+" Last Change: 2025 Jan 22
+
+if exists("b:current_syntax")
+ finish
+endif
+
+" Comments: whole line from '#'
+syn match skhdComment /^\s*#.*/
+
+" Modifiers (shift, ctrl, alt, cmd, fn)
+syn keyword skhdModifier
+ \ alt lalt ralt
+ \ shift lshift rshift
+ \ cmd lcmd rcmd
+ \ ctrl lctrl rctrl
+ \ fn hyper meh
+ \ option super
+" highlight the '+' and '-' and ':' separators
+syn match skhdOperator /->/
+syn match skhdOperator /[+:\-;<>,\[\]@~]/
+
+" Hex keycode form: 0x3C etc
+syn match skhdKeycode /\v0x[0-9A-Fa-f]+/
+
+" Keys (a–z, digits, function‐keys, arrows…)
+syn keyword skhdKey
+ \ return tab space backspace escape delete
+ \ home end pageup pagedown insert
+ \ left right up down
+ \ sound_up sound_down mute play previous next rewind fast
+ \ brightness_up brightness_down illumination_up illumination_down
+syn match skhdKey /\vf([1-9]|1[0-9]|20)\>/
+syn match skhdKey /\v\<[A-Za-z0-9]\>/
+
+" The yabai command and its subcommands
+syn match skhdCommand /\<yabai\>\|\<open\>/
+syn match skhdSubCmd /\<window\>\|\<space\>\|\<display\>/
+
+" ───────────────────────────────────────────────────────────────────
+" Treat anything after a single “:” (not double‑colon) as bash
+" ───────────────────────────────────────────────────────────────────
+" load Vim’s built‑in shell rules
+syntax include @bash syntax/bash.vim
+
+" After `:` (not `::`) is a bash command, but not when it is preceded by a `\`
+syn region skhdBash
+ \ matchgroup=skhdOperator
+ \ start=/\v(^|[^:])\zs:\s*/
+ \ end=/\v\s*$\ze/
+ \ skip=/\v\\\s*$/
+ \ keepend
+ \ contains=@bash
+
+" ────────────────────────────────────────────────────────────────
+" Key‑map group definitions and switches
+" ────────────────────────────────────────────────────────────────
+" In skhd, you can define groups and assign hotkeys to them as follows:
+" 1. Group‑definition lines that start with :: <group>
+" 2. Switch operator (<)
+" 3. Target group names after the ;
+
+" Lines like `:: default` or `:: passthrough`
+" match the whole thing as a GroupDef, but capture the group name
+syn match skhdGroupDef /^::\s*\w\+/
+syn match skhdGroupName /::\s*\zs\w\+/
+
+" The `<` switch token in lines like
+" passthrough < cmd + shift + alt - b ; default
+syn match skhdSwitch /<\s*/
+
+" The target (or “fall‑through”) group after the semicolon
+" ... ; default
+syn match skhdTargetGroup /;\s*\zs\w\+/
+
+
+" ------------------------------------------------------------
+" Application-specific bindings block: <keysym> [ ... ]
+" ------------------------------------------------------------
+
+" The whole block. This avoids grabbing .blacklist by requiring the line be just '[' at end.
+syn region skhdProcMapBlock
+ \ matchgroup=skhdProcMapDelim
+ \ start=/\v\[\s*$/
+ \ end=/^\s*\]\s*$/
+ \ keepend
+ \ transparent
+ \ contains=skhdProcMapApp,skhdProcMapWildcard,skhdProcMapUnbind,skhdOperator,skhdComment,skhdBash,skhdString
+
+" App name on the left side: "Google Chrome" :
+syn match skhdProcMapApp /^\s*\zs"[^"]*"\ze\s*:\s*/ contained
+
+" Wildcard entry: * :
+syn match skhdProcMapWildcard /^\s*\zs\*\ze\s*:\s*/ contained
+
+" Unbind operator on the right side: "App" ~ or * ~
+syn match skhdProcMapUnbind /\v^\s*(\"[^"]*\"|\*)\s*\zs\~\ze\s*$/ contained
+
+syn keyword skhdDirective .load .blacklist
+syn match skhdLoadLine /^\s*\.load\>\s\+/ contains=skhdDirective
+
+syn region skhdBlacklistBlock
+ \ start=/^\s*\.blacklist\>\s*\[\s*$/
+ \ end=/^\s*\]\s*$/
+ \ keepend
+ \ contains=skhdDirective,skhdComment,skhdString
+
+syn region skhdString start=/"/ skip=/\\"/ end=/"/
+
+" ────────────────────────────────────────────────────────────────
+" Linking to standard Vim highlight groups
+" ────────────────────────────────────────────────────────────────
+hi def link skhdComment Comment
+hi def link skhdHeadline Title
+hi def link skhdModifier Keyword
+hi def link skhdOperator Operator
+hi def link skhdWildcard Special
+hi def link skhdKey Identifier
+hi def link skhdKeycode Number
+hi def link skhdCommand Function
+hi def link skhdSubCmd Statement
+hi def link skhdGroupDef Label
+hi def link skhdGroupName Identifier
+hi def link skhdSwitch Operator
+hi def link skhdTargetGroup Type
+hi def link skhdString String
+
+hi def link skhdProcMapDelim Operator
+hi def link skhdProcMapApp Type
+hi def link skhdProcMapWildcard Special
+hi def link skhdProcMapUnbind Special
+
+hi def link skhdDirective PreProc
+
+let b:current_syntax = "skhd"
diff --git a/test/old/testdir/test_filetype.vim b/test/old/testdir/test_filetype.vim
@@ -738,6 +738,7 @@ func s:GetFilenameChecks() abort
\ 'simula': ['file.sim'],
\ 'sinda': ['file.sin', 'file.s85'],
\ 'sisu': ['file.sst', 'file.ssm', 'file.ssi', 'file.-sst', 'file._sst', 'file.sst.meta', 'file.-sst.meta', 'file._sst.meta'],
+ \ 'skhd': ['.skhdrc', 'skhdrc'],
\ 'skill': ['file.il', 'file.ils', 'file.cdf'],
\ 'slang': ['file.sl'],
\ 'slice': ['file.ice'],