Skip to content

Instantly share code, notes, and snippets.

@td2sk
Last active March 24, 2023 17:39
Show Gist options
  • Save td2sk/99cc1f0f5340d16314e9e421aa7278e7 to your computer and use it in GitHub Desktop.
Save td2sk/99cc1f0f5340d16314e9e421aa7278e7 to your computer and use it in GitHub Desktop.
tool for VSCode for QMK development

QMK VSCode 設定

概要

  • QMK の開発時に VSCode で補完が適切に効くようにするツール
  • qmk generate-compilation-database コマンドと違い、keymap.c でも適切に動作する

事前準備

最低限の設定を記載した $QMK_ROOT/.vscode/c_cpp_properties.json を事前に作成しておく

以下は Windows の例

{
    "configurations": [
        {
            "name": "Win32",
            "intelliSenseMode": "clang-x64",
            "compilerPath": "C:/QMK_MSYS/mingw64/bin/avr-gcc.exe",
            "cStandard": "c11",
            "cppStandard": "c++17"
        }
    ],
    "version": 4
}

設定反映

手動実行の場合

  1. (rules.mk等を編集した場合) qmk compile を実行
  2. update_qmk_c_cpp_properties.py を実行

実行すると、$QMK_ROOT/.vscode/c_cpp_properties.json に適切な定義が挿入される

変更のたびに上記 1, 2 の手順を実行する必要がある

自動実行(変更検知モード)の場合

  1. update_qmk_c_cpp_properties.py を --watch オプション付きで実行
  2. (rules.mk等を編集した場合) qmk compile を実行

以降は qmk compile のたびに自動で更新される

オプション

  • -kb, --keyboard (必須)
    • キーボードを指定
    • qmk コマンドに渡すものと同様
  • -km, --keymap (必須)
    • キーマップを指定
    • qmk コマンドに渡すものと同様
  • --watch
    • 更新検知モード
    • watchdog の事前インストールが必要
      • pip install watchdog
import argparse
import json
import os
import shlex
import sys
import time
C_CPP_PROPERTIES_PATH = "./.vscode/c_cpp_properties.json"
def watch(action, path: str):
print("error: watchdog is not installed.", file=sys.stderr)
print("If you use the --watch option, you should install watchdog.", file=sys.stderr)
print("> pip install watchdog", file=sys.stderr)
exit(1)
try:
from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer
class ChangeHandler(FileSystemEventHandler):
def __init__(self, action):
super().__init__()
self.action = action
def on_modified(self, event):
self.action()
print("update .vscode/c_cpp_properties.json")
def watch(action, path: str):
handler = ChangeHandler(action)
observer = Observer()
observer.schedule(handler, os.path.dirname(path))
observer.start()
print("watching...")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
except ImportError:
pass
def get_cflags_path(keyboard: str, keymap: str):
return f"./.build/obj_{keyboard}_{keymap}/cflags.txt"
def parse_cflags(path: str):
with open(path) as f:
cflags = f.read()
parser = argparse.ArgumentParser()
parser.add_argument('-D', action="append")
parser.add_argument('-I', action="append")
parser.add_argument('-include', action="append")
args, _ = parser.parse_known_args(shlex.split(cflags))
return args
def main(keyboard: str, keymap: str):
args = parse_cflags(get_cflags_path(keyboard, keymap))
with open(C_CPP_PROPERTIES_PATH, "r") as f:
props = json.load(f)
for conf in props['configurations']:
conf["defines"] = args.D
conf["includePath"] = ["${workspaceFolder}/" + arg for arg in args.I]
conf["forcedInclude"] = ["${workspaceFolder}/" + arg for arg in args.include]
with open(C_CPP_PROPERTIES_PATH, "w") as f:
json.dump(props, f, indent=4, ensure_ascii=False)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-kb", "--keyboard", required=True)
parser.add_argument("-km", "--keymap", required=True)
parser.add_argument("--watch", action="store_true", default=False)
args = parser.parse_args()
action = lambda: main(args.keyboard, args.keymap)
action()
if args.watch:
watch(action, get_cflags_path(args.keyboard, args.keymap))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment