feat(docs): add keymap upgrader
Added a documentation page with a script that upgrades deprecated key codes and behaviors to their replacements. Fixes #299
This commit is contained in:
parent
77c16b020e
commit
5aa8a07aa9
12 changed files with 562 additions and 4 deletions
21
docs/docs/codes/keymap-upgrader.mdx
Normal file
21
docs/docs/codes/keymap-upgrader.mdx
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
title: Keymap Upgrader
|
||||||
|
sidebar_label: Keymap Upgrader
|
||||||
|
hide_title: true
|
||||||
|
hide_table_of_contents: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Keymap Upgrader
|
||||||
|
|
||||||
|
Many codes have been renamed to be more consistent with each other.
|
||||||
|
Paste the contents of a `.keymap` file below to upgrade all deprecated codes to their replacements.
|
||||||
|
|
||||||
|
Hover your mouse over the upgraded keymap and click the `Copy` button to copy it to your clipboard.
|
||||||
|
|
||||||
|
You will likely need to realign columns in the upgraded keymap. The upgrader also does not handle
|
||||||
|
codes inside a `#define`, so you will need to update those manually using
|
||||||
|
[this list of deprecated codes and replacements](https://github.com/zmkfirmware/zmk/blob/main/docs/src/data/keymap-upgrade.js).
|
||||||
|
|
||||||
|
import KeymapUpgrader from "@site/src/components/KeymapUpgrader/index";
|
||||||
|
|
||||||
|
<KeymapUpgrader />
|
|
@ -1,3 +1,5 @@
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
title: "ZMK Firmware",
|
title: "ZMK Firmware",
|
||||||
tagline: "Modern, open source keyboard firmware",
|
tagline: "Modern, open source keyboard firmware",
|
||||||
|
@ -6,6 +8,7 @@ module.exports = {
|
||||||
favicon: "img/favicon.ico",
|
favicon: "img/favicon.ico",
|
||||||
organizationName: "zmkfirmware", // Usually your GitHub org/user name.
|
organizationName: "zmkfirmware", // Usually your GitHub org/user name.
|
||||||
projectName: "zmk", // Usually your repo name.
|
projectName: "zmk", // Usually your repo name.
|
||||||
|
plugins: [path.resolve(__dirname, "src/docusaurus-tree-sitter-plugin")],
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
googleAnalytics: {
|
googleAnalytics: {
|
||||||
trackingID: "UA-145201102-2",
|
trackingID: "UA-145201102-2",
|
||||||
|
|
105
docs/package-lock.json
generated
105
docs/package-lock.json
generated
|
@ -14,16 +14,20 @@
|
||||||
"@fortawesome/react-fontawesome": "^0.1.12",
|
"@fortawesome/react-fontawesome": "^0.1.12",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"react": "^16.8.4",
|
"react": "^16.8.4",
|
||||||
|
"react-async": "^10.0.1",
|
||||||
"react-copy-to-clipboard": "^5.0.2",
|
"react-copy-to-clipboard": "^5.0.2",
|
||||||
"react-dom": "^16.8.4",
|
"react-dom": "^16.8.4",
|
||||||
"react-toastify": "^6.0.9"
|
"react-toastify": "^6.0.9",
|
||||||
|
"web-tree-sitter": "^0.17.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^7.12.0",
|
"eslint": "^7.12.0",
|
||||||
"eslint-config-prettier": "^6.14.0",
|
"eslint-config-prettier": "^6.14.0",
|
||||||
"eslint-plugin-mdx": "^1.8.2",
|
"eslint-plugin-mdx": "^1.8.2",
|
||||||
"eslint-plugin-react": "^7.21.5",
|
"eslint-plugin-react": "^7.21.5",
|
||||||
"prettier": "2.1.2"
|
"null-loader": "^3.0.0",
|
||||||
|
"prettier": "2.1.2",
|
||||||
|
"string-replace-loader": "2.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@algolia/cache-browser-local-storage": {
|
"node_modules/@algolia/cache-browser-local-storage": {
|
||||||
|
@ -11321,6 +11325,14 @@
|
||||||
"prop-types": "15.7.2"
|
"prop-types": "15.7.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-async": {
|
||||||
|
"version": "10.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-async/-/react-async-10.0.1.tgz",
|
||||||
|
"integrity": "sha512-ORUz5ca0B57QgBIzEZM5SuhJ6xFjkvEEs0gylLNlWf06vuVcLZsjIw3wx58jJkZG38p+0nUAxRgFW2b7mnVZzA==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-base16-styling": {
|
"node_modules/react-base16-styling": {
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz",
|
||||||
|
@ -13334,6 +13346,45 @@
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/string-replace-loader": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-replace-loader/-/string-replace-loader-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-HYBIHStViMKLZC/Lehxy42OuwsBaPzX/LjcF5mkJlE2SnHXmW6SW6eiHABTXnY8ZCm/REbdJ8qnA0ptmIzN0Ng==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"loader-utils": "^1.2.3",
|
||||||
|
"schema-utils": "^2.6.5"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"webpack": "1 || 2 || 3 || 4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/string-replace-loader/node_modules/json5": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"minimist": "^1.2.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"json5": "lib/cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/string-replace-loader/node_modules/loader-utils": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"big.js": "^5.2.2",
|
||||||
|
"emojis-list": "^3.0.0",
|
||||||
|
"json5": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/string-width": {
|
"node_modules/string-width": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
|
||||||
|
@ -14794,6 +14845,7 @@
|
||||||
"version": "1.2.13",
|
"version": "1.2.13",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
|
||||||
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
|
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
|
||||||
|
"hasInstallScript": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bindings": "1.5.0",
|
"bindings": "1.5.0",
|
||||||
|
@ -14929,6 +14981,11 @@
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/web-tree-sitter": {
|
||||||
|
"version": "0.17.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.17.1.tgz",
|
||||||
|
"integrity": "sha512-QgaeV+wmlB1Qaw9rS5a0ZDBt8GRcKkF+hGNSVxQ/HLm1lPCow3BKOhoILaXkYm7YozCcL7TjppRADBwFJugbuA=="
|
||||||
|
},
|
||||||
"node_modules/webidl-conversions": {
|
"node_modules/webidl-conversions": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
|
||||||
|
@ -15202,6 +15259,7 @@
|
||||||
"version": "1.2.13",
|
"version": "1.2.13",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
|
||||||
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
|
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
|
||||||
|
"hasInstallScript": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bindings": "1.5.0",
|
"bindings": "1.5.0",
|
||||||
|
@ -26900,6 +26958,12 @@
|
||||||
"prop-types": "15.7.2"
|
"prop-types": "15.7.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-async": {
|
||||||
|
"version": "10.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-async/-/react-async-10.0.1.tgz",
|
||||||
|
"integrity": "sha512-ORUz5ca0B57QgBIzEZM5SuhJ6xFjkvEEs0gylLNlWf06vuVcLZsjIw3wx58jJkZG38p+0nUAxRgFW2b7mnVZzA==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"react-base16-styling": {
|
"react-base16-styling": {
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.6.0.tgz",
|
||||||
|
@ -28878,6 +28942,38 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"string-replace-loader": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-replace-loader/-/string-replace-loader-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-HYBIHStViMKLZC/Lehxy42OuwsBaPzX/LjcF5mkJlE2SnHXmW6SW6eiHABTXnY8ZCm/REbdJ8qnA0ptmIzN0Ng==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"loader-utils": "^1.2.3",
|
||||||
|
"schema-utils": "^2.6.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"json5": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"minimist": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"loader-utils": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"big.js": "^5.2.2",
|
||||||
|
"emojis-list": "^3.0.0",
|
||||||
|
"json5": "^1.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
|
||||||
|
@ -30421,6 +30517,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz",
|
||||||
"integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw=="
|
"integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw=="
|
||||||
},
|
},
|
||||||
|
"web-tree-sitter": {
|
||||||
|
"version": "0.17.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.17.1.tgz",
|
||||||
|
"integrity": "sha512-QgaeV+wmlB1Qaw9rS5a0ZDBt8GRcKkF+hGNSVxQ/HLm1lPCow3BKOhoILaXkYm7YozCcL7TjppRADBwFJugbuA=="
|
||||||
|
},
|
||||||
"webidl-conversions": {
|
"webidl-conversions": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
|
||||||
|
|
|
@ -21,9 +21,11 @@
|
||||||
"@fortawesome/react-fontawesome": "^0.1.12",
|
"@fortawesome/react-fontawesome": "^0.1.12",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"react": "^16.8.4",
|
"react": "^16.8.4",
|
||||||
|
"react-async": "^10.0.1",
|
||||||
"react-copy-to-clipboard": "^5.0.2",
|
"react-copy-to-clipboard": "^5.0.2",
|
||||||
"react-dom": "^16.8.4",
|
"react-dom": "^16.8.4",
|
||||||
"react-toastify": "^6.0.9"
|
"react-toastify": "^6.0.9",
|
||||||
|
"web-tree-sitter": "^0.17.1"
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
|
@ -42,6 +44,8 @@
|
||||||
"eslint-config-prettier": "^6.14.0",
|
"eslint-config-prettier": "^6.14.0",
|
||||||
"eslint-plugin-mdx": "^1.8.2",
|
"eslint-plugin-mdx": "^1.8.2",
|
||||||
"eslint-plugin-react": "^7.21.5",
|
"eslint-plugin-react": "^7.21.5",
|
||||||
"prettier": "2.1.2"
|
"null-loader": "^3.0.0",
|
||||||
|
"prettier": "2.1.2",
|
||||||
|
"string-replace-loader": "2.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ module.exports = {
|
||||||
"codes/applications",
|
"codes/applications",
|
||||||
"codes/input-assist",
|
"codes/input-assist",
|
||||||
"codes/power",
|
"codes/power",
|
||||||
|
"codes/keymap-upgrader",
|
||||||
],
|
],
|
||||||
Development: [
|
Development: [
|
||||||
"development/clean-room",
|
"development/clean-room",
|
||||||
|
|
47
docs/src/components/KeymapUpgrader/index.jsx
Normal file
47
docs/src/components/KeymapUpgrader/index.jsx
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: CC-BY-NC-SA-4.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { useAsync } from "react-async";
|
||||||
|
|
||||||
|
import { initParser, upgradeKeymap } from "@site/src/keymap-upgrade";
|
||||||
|
import CodeBlock from "@theme/CodeBlock";
|
||||||
|
|
||||||
|
import styles from "./styles.module.css";
|
||||||
|
|
||||||
|
export default function KeymapUpgrader() {
|
||||||
|
const { error, isPending } = useAsync(initParser);
|
||||||
|
|
||||||
|
if (isPending) {
|
||||||
|
return <p>Loading...</p>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return <p className="error">Error: {error.message}</p>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Editor />;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Editor() {
|
||||||
|
const [keymap, setKeymap] = React.useState("");
|
||||||
|
const upgraded = upgradeKeymap(keymap);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<textarea
|
||||||
|
className={styles.editor}
|
||||||
|
placeholder="Paste keymap here"
|
||||||
|
spellCheck={false}
|
||||||
|
value={keymap}
|
||||||
|
onChange={(e) => setKeymap(e.target.value)}
|
||||||
|
></textarea>
|
||||||
|
<div className={styles.result}>
|
||||||
|
<CodeBlock metastring={'title="Upgraded Keymap"'}>{upgraded}</CodeBlock>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
26
docs/src/components/KeymapUpgrader/styles.module.css
Normal file
26
docs/src/components/KeymapUpgrader/styles.module.css
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: CC-BY-NC-SA-4.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
.editor {
|
||||||
|
font-family: var(--ifm-font-family-monospace);
|
||||||
|
font-size: var(--ifm-font-size-base);
|
||||||
|
line-height: var(--ifm-pre-line-height);
|
||||||
|
tab-size: 4;
|
||||||
|
|
||||||
|
color: var(--ifm-pre-color);
|
||||||
|
background-color: var(--ifm-pre-background);
|
||||||
|
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--ifm-pre-border-radius);
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
min-height: 10em;
|
||||||
|
padding: var(--ifm-pre-padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
.result {
|
||||||
|
tab-size: 4;
|
||||||
|
}
|
84
docs/src/data/keymap-upgrade.js
Normal file
84
docs/src/data/keymap-upgrade.js
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: CC-BY-NC-SA-4.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const Codes = {
|
||||||
|
NUM_1: "N1",
|
||||||
|
NUM_2: "N2",
|
||||||
|
NUM_3: "N3",
|
||||||
|
NUM_4: "N4",
|
||||||
|
NUM_5: "N5",
|
||||||
|
NUM_6: "N6",
|
||||||
|
NUM_7: "N7",
|
||||||
|
NUM_8: "N8",
|
||||||
|
NUM_9: "N9",
|
||||||
|
NUM_0: "N0",
|
||||||
|
BKSP: "BSPC",
|
||||||
|
SPC: "SPACE",
|
||||||
|
EQL: "EQUAL",
|
||||||
|
TILD: "TILDE",
|
||||||
|
SCLN: "SEMI",
|
||||||
|
QUOT: "SQT",
|
||||||
|
GRAV: "GRAVE",
|
||||||
|
CMMA: "COMMA",
|
||||||
|
PRSC: "PSCRN",
|
||||||
|
SCLK: "SLCK",
|
||||||
|
PAUS: "PAUSE_BREAK",
|
||||||
|
PGUP: "PG_UP",
|
||||||
|
PGDN: "PG_DN",
|
||||||
|
RARW: "RIGHT",
|
||||||
|
LARW: "LEFT",
|
||||||
|
DARW: "DOWN",
|
||||||
|
UARW: "UP",
|
||||||
|
KDIV: "KP_DIVIDE",
|
||||||
|
KMLT: "KP_MULTIPLY",
|
||||||
|
KMIN: "KP_MINUS",
|
||||||
|
KPLS: "KP_PLUS",
|
||||||
|
UNDO: "K_UNDO",
|
||||||
|
CUT: "K_CUT",
|
||||||
|
COPY: "K_COPY",
|
||||||
|
PSTE: "K_PASTE",
|
||||||
|
VOLU: "K_VOL_UP",
|
||||||
|
VOLD: "K_VOL_DN",
|
||||||
|
CURU: "DLLR",
|
||||||
|
LPRN: "LPAR",
|
||||||
|
RPRN: "RPAR",
|
||||||
|
LCUR: "LBRC",
|
||||||
|
RCUR: "RBRC",
|
||||||
|
CRRT: "CARET",
|
||||||
|
PRCT: "PRCNT",
|
||||||
|
LABT: "LT",
|
||||||
|
RABT: "GT",
|
||||||
|
COLN: "COLON",
|
||||||
|
KSPC: null,
|
||||||
|
ATSN: "AT",
|
||||||
|
BANG: "EXCL",
|
||||||
|
LCTL: "LCTRL",
|
||||||
|
LSFT: "LSHFT",
|
||||||
|
RCTL: "RCTRL",
|
||||||
|
RSFT: "RSHFT",
|
||||||
|
M_NEXT: "C_NEXT",
|
||||||
|
M_PREV: "C_PREV",
|
||||||
|
M_STOP: "C_STOP",
|
||||||
|
M_EJCT: "C_EJECT",
|
||||||
|
M_PLAY: "C_PP",
|
||||||
|
M_MUTE: "C_MUTE",
|
||||||
|
M_VOLU: "C_VOL_UP",
|
||||||
|
M_VOLD: "C_VOL_DN",
|
||||||
|
GUI: "K_CMENU",
|
||||||
|
MOD_LCTL: "LCTRL",
|
||||||
|
MOD_LSFT: "LSHFT",
|
||||||
|
MOD_LALT: "LALT",
|
||||||
|
MOD_LGUI: "LGUI",
|
||||||
|
MOD_RCTL: "RCTRL",
|
||||||
|
MOD_RSFT: "RSHFT",
|
||||||
|
MOD_RALT: "RALT",
|
||||||
|
MOD_RGUI: "RGUI",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Behaviors = {
|
||||||
|
cp: "kp",
|
||||||
|
inc_dec_cp: "inc_dec_kp",
|
||||||
|
};
|
39
docs/src/docusaurus-tree-sitter-plugin/index.js
Normal file
39
docs/src/docusaurus-tree-sitter-plugin/index.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
module.exports = function () {
|
||||||
|
return {
|
||||||
|
configureWebpack(config, isServer) {
|
||||||
|
let rules = [];
|
||||||
|
|
||||||
|
// Tree-sitter is only used for client-side code.
|
||||||
|
// Don't try to load it on the server.
|
||||||
|
if (isServer) {
|
||||||
|
rules.push({
|
||||||
|
test: /web-tree-sitter/,
|
||||||
|
loader: "null-loader",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// web-tree-sitter has a hard-coded path to tree-sitter.wasm,
|
||||||
|
// (see https://github.com/tree-sitter/tree-sitter/issues/559)
|
||||||
|
// which some browsers treat as absolute and others as relative.
|
||||||
|
// This breaks everything. Rewrite it to always use an absolute path.
|
||||||
|
rules.push({
|
||||||
|
test: /tree-sitter\.js$/,
|
||||||
|
loader: "string-replace-loader",
|
||||||
|
options: {
|
||||||
|
search: '"tree-sitter.wasm"',
|
||||||
|
replace: '"/tree-sitter.wasm"',
|
||||||
|
strict: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
// web-tree-sitter tries to import "fs", which can be ignored.
|
||||||
|
// https://github.com/tree-sitter/tree-sitter/issues/466
|
||||||
|
node: {
|
||||||
|
fs: "empty",
|
||||||
|
},
|
||||||
|
module: { rules },
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
232
docs/src/keymap-upgrade.js
Normal file
232
docs/src/keymap-upgrade.js
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
import Parser from "web-tree-sitter";
|
||||||
|
|
||||||
|
import { Codes, Behaviors } from "./data/keymap-upgrade";
|
||||||
|
|
||||||
|
let Devicetree;
|
||||||
|
|
||||||
|
export async function initParser() {
|
||||||
|
await Parser.init();
|
||||||
|
Devicetree = await Parser.Language.load("/tree-sitter-devicetree.wasm");
|
||||||
|
}
|
||||||
|
|
||||||
|
function createParser() {
|
||||||
|
if (!Devicetree) {
|
||||||
|
throw new Error("Parser not loaded. Call initParser() first.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const parser = new Parser();
|
||||||
|
parser.setLanguage(Devicetree);
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function upgradeKeymap(text) {
|
||||||
|
const parser = createParser();
|
||||||
|
const tree = parser.parse(text);
|
||||||
|
|
||||||
|
const edits = [...upgradeBehaviors(tree), ...upgradeKeycodes(tree)];
|
||||||
|
|
||||||
|
return applyEdits(text, edits);
|
||||||
|
}
|
||||||
|
|
||||||
|
class TextEdit {
|
||||||
|
/**
|
||||||
|
* Creates a text edit to replace a range or node with new text.
|
||||||
|
* Construct with one of:
|
||||||
|
*
|
||||||
|
* * `Edit(startIndex, endIndex, newText)`
|
||||||
|
* * `Edit(node, newText)`
|
||||||
|
*/
|
||||||
|
constructor(startIndex, endIndex, newText) {
|
||||||
|
if (typeof startIndex !== "number") {
|
||||||
|
const node = startIndex;
|
||||||
|
newText = endIndex;
|
||||||
|
startIndex = node.startIndex;
|
||||||
|
endIndex = node.endIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type number */
|
||||||
|
this.startIndex = startIndex;
|
||||||
|
/** @type number */
|
||||||
|
this.endIndex = endIndex;
|
||||||
|
/** @type string */
|
||||||
|
this.newText = newText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upgrades deprecated behavior references.
|
||||||
|
* @param {Parser.Tree} tree
|
||||||
|
*/
|
||||||
|
function upgradeBehaviors(tree) {
|
||||||
|
/** @type TextEdit[] */
|
||||||
|
let edits = [];
|
||||||
|
|
||||||
|
const query = Devicetree.query("(reference label: (identifier) @ref)");
|
||||||
|
const matches = query.matches(tree.rootNode);
|
||||||
|
|
||||||
|
for (const { captures } of matches) {
|
||||||
|
const node = findCapture("ref", captures);
|
||||||
|
if (node) {
|
||||||
|
edits.push(...getUpgradeEdits(node, Behaviors));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return edits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upgrades deprecated key code identifiers.
|
||||||
|
* @param {Parser.Tree} tree
|
||||||
|
*/
|
||||||
|
function upgradeKeycodes(tree) {
|
||||||
|
/** @type TextEdit[] */
|
||||||
|
let edits = [];
|
||||||
|
|
||||||
|
// No need to filter to the bindings array. The C preprocessor would have
|
||||||
|
// replaced identifiers anywhere, so upgrading all identifiers preserves the
|
||||||
|
// original behavior of the keymap (even if that behavior wasn't intended).
|
||||||
|
const query = Devicetree.query("(identifier) @name");
|
||||||
|
const matches = query.matches(tree.rootNode);
|
||||||
|
|
||||||
|
for (const { captures } of matches) {
|
||||||
|
const node = findCapture("name", captures);
|
||||||
|
if (node) {
|
||||||
|
edits.push(...getUpgradeEdits(node, Codes, keycodeReplaceHandler));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return edits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Parser.SyntaxNode} node
|
||||||
|
* @param {string | null} replacement
|
||||||
|
* @returns TextEdit[]
|
||||||
|
*/
|
||||||
|
function keycodeReplaceHandler(node, replacement) {
|
||||||
|
if (replacement) {
|
||||||
|
return [new TextEdit(node, replacement)];
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodes = findBehaviorNodes(node);
|
||||||
|
|
||||||
|
if (nodes.length === 0) {
|
||||||
|
console.warn(
|
||||||
|
`Found deprecated code "${node.text}" but it is not a parameter to a behavior`
|
||||||
|
);
|
||||||
|
return [new TextEdit(node, `/* "${node.text}" no longer exists */`)];
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldText = nodes.map((n) => n.text).join(" ");
|
||||||
|
const newText = `&none /* "${oldText}" no longer exists */`;
|
||||||
|
|
||||||
|
const startIndex = nodes[0].startIndex;
|
||||||
|
const endIndex = nodes[nodes.length - 1].endIndex;
|
||||||
|
|
||||||
|
return [new TextEdit(startIndex, endIndex, newText)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the node for the named capture.
|
||||||
|
* @param {string} name
|
||||||
|
* @param {any[]} captures
|
||||||
|
* @returns {Parser.SyntaxNode | null}
|
||||||
|
*/
|
||||||
|
function findCapture(name, captures) {
|
||||||
|
for (const c of captures) {
|
||||||
|
if (c.name === name) {
|
||||||
|
return c.node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a parameter to a keymap behavior, returns a list of nodes beginning
|
||||||
|
* with the behavior and including all parameters.
|
||||||
|
* Returns an empty array if no behavior was found.
|
||||||
|
* @param {Parser.SyntaxNode} paramNode
|
||||||
|
*/
|
||||||
|
function findBehaviorNodes(paramNode) {
|
||||||
|
// Walk backwards from the given parameter to find the behavior reference.
|
||||||
|
let behavior = paramNode.previousNamedSibling;
|
||||||
|
while (behavior && behavior.type !== "reference") {
|
||||||
|
behavior = behavior.previousNamedSibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!behavior) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk forward from the behavior to collect all its parameters.
|
||||||
|
|
||||||
|
let nodes = [behavior];
|
||||||
|
let param = behavior.nextNamedSibling;
|
||||||
|
while (param && param.type !== "reference") {
|
||||||
|
nodes.push(param);
|
||||||
|
param = param.nextNamedSibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of text edits to apply based on a node and a map of text
|
||||||
|
* replacements.
|
||||||
|
*
|
||||||
|
* If replaceHandler is given, it will be called if the node matches a
|
||||||
|
* deprecated value and it should return the text edits to apply.
|
||||||
|
*
|
||||||
|
* @param {Parser.SyntaxNode} node
|
||||||
|
* @param {Map<string, string | null>} replacementMap
|
||||||
|
* @param {(node: Parser.SyntaxNode, replacement: string | null) => TextEdit[]} replaceHandler
|
||||||
|
*/
|
||||||
|
function getUpgradeEdits(node, replacementMap, replaceHandler = undefined) {
|
||||||
|
for (const [deprecated, replacement] of Object.entries(replacementMap)) {
|
||||||
|
if (node.text === deprecated) {
|
||||||
|
if (replaceHandler) {
|
||||||
|
return replaceHandler(node, replacement);
|
||||||
|
} else {
|
||||||
|
return [new TextEdit(node, replacement)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts a list of text edits in ascending order by position.
|
||||||
|
* @param {TextEdit[]} edits
|
||||||
|
*/
|
||||||
|
function sortEdits(edits) {
|
||||||
|
return edits.sort((a, b) => a.startIndex - b.startIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string with text replacements applied.
|
||||||
|
* @param {string} text
|
||||||
|
* @param {TextEdit[]} edits
|
||||||
|
*/
|
||||||
|
function applyEdits(text, edits) {
|
||||||
|
edits = sortEdits(edits);
|
||||||
|
|
||||||
|
/** @type string[] */
|
||||||
|
const chunks = [];
|
||||||
|
let currentIndex = 0;
|
||||||
|
|
||||||
|
for (const edit of edits) {
|
||||||
|
if (edit.startIndex < currentIndex) {
|
||||||
|
console.warn("discarding overlapping edit", edit);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunks.push(text.substring(currentIndex, edit.startIndex));
|
||||||
|
chunks.push(edit.newText);
|
||||||
|
currentIndex = edit.endIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunks.push(text.substring(currentIndex));
|
||||||
|
|
||||||
|
return chunks.join("");
|
||||||
|
}
|
BIN
docs/static/tree-sitter-devicetree.wasm
vendored
Normal file
BIN
docs/static/tree-sitter-devicetree.wasm
vendored
Normal file
Binary file not shown.
BIN
docs/static/tree-sitter.wasm
vendored
Normal file
BIN
docs/static/tree-sitter.wasm
vendored
Normal file
Binary file not shown.
Loading…
Reference in a new issue