From 12967f2819e2bd42a24596bb6532680e5a97280f Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Mon, 25 Apr 2022 20:34:09 +0200 Subject: [PATCH 01/16] use codemirror 6 --- repl/package-lock.json | 579 +++++++++++++++++++++++++++++++++++++++ repl/package.json | 3 + repl/src/App.js | 61 +++-- repl/src/CodeMirror6.jsx | 188 +++++++++++++ 4 files changed, 807 insertions(+), 24 deletions(-) create mode 100644 repl/src/CodeMirror6.jsx diff --git a/repl/package-lock.json b/repl/package-lock.json index e58864b3..abe99f12 100644 --- a/repl/package-lock.json +++ b/repl/package-lock.json @@ -8,14 +8,17 @@ "name": "@strudel.cycles/repl", "version": "0.1.0", "dependencies": { + "@codemirror/lang-javascript": "^0.19.0", "@testing-library/jest-dom": "^5.16.3", "@testing-library/react": "^12.1.4", "@testing-library/user-event": "^13.5.0", "codemirror": "^5.65.2", + "codemirror6-themes": "^0.1.2", "events": "^3.3.0", "gh-pages": "^3.2.3", "react": "^17.0.2", "react-codemirror2": "^7.2.1", + "react-codemirror6": "^1.1.0", "react-dom": "^17.0.2", "react-scripts": "5.0.0", "tone": "^14.7.77", @@ -1857,6 +1860,223 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, + "node_modules/@codemirror/autocomplete": { + "version": "0.19.15", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-0.19.15.tgz", + "integrity": "sha512-GQWzvvuXxNUyaEk+5gawbAD8s51/v2Chb++nx0e2eGWrphWk42isBtzOMdc3DxrxrZtPZ55q2ldNp+6G8KJLIQ==", + "dependencies": { + "@codemirror/language": "^0.19.0", + "@codemirror/state": "^0.19.4", + "@codemirror/text": "^0.19.2", + "@codemirror/tooltip": "^0.19.12", + "@codemirror/view": "^0.19.0", + "@lezer/common": "^0.15.0" + } + }, + "node_modules/@codemirror/closebrackets": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@codemirror/closebrackets/-/closebrackets-0.19.2.tgz", + "integrity": "sha512-ClMPzPcPP0eQiDcVjtVPl6OLxgdtZSYDazsvT0AKl70V1OJva0eHgl4/6kCW3RZ0pb2n34i9nJz4eXCmK+TYDA==", + "dependencies": { + "@codemirror/language": "^0.19.0", + "@codemirror/rangeset": "^0.19.0", + "@codemirror/state": "^0.19.2", + "@codemirror/text": "^0.19.0", + "@codemirror/view": "^0.19.44" + } + }, + "node_modules/@codemirror/commands": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-0.19.8.tgz", + "integrity": "sha512-65LIMSGUGGpY3oH6mzV46YWRrgao6NmfJ+AuC7jNz3K5NPnH6GCV1H5I6SwOFyVbkiygGyd0EFwrWqywTBD1aw==", + "dependencies": { + "@codemirror/language": "^0.19.0", + "@codemirror/matchbrackets": "^0.19.0", + "@codemirror/state": "^0.19.2", + "@codemirror/text": "^0.19.6", + "@codemirror/view": "^0.19.22", + "@lezer/common": "^0.15.0" + } + }, + "node_modules/@codemirror/comment": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@codemirror/comment/-/comment-0.19.1.tgz", + "integrity": "sha512-uGKteBuVWAC6fW+Yt8u27DOnXMT/xV4Ekk2Z5mRsiADCZDqYvryrJd6PLL5+8t64BVyocwQwNfz1UswYS2CtFQ==", + "dependencies": { + "@codemirror/state": "^0.19.9", + "@codemirror/text": "^0.19.0", + "@codemirror/view": "^0.19.0" + } + }, + "node_modules/@codemirror/fold": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@codemirror/fold/-/fold-0.19.4.tgz", + "integrity": "sha512-0SNSkRSOa6gymD6GauHa3sxiysjPhUC0SRVyTlvL52o0gz9GHdc8kNqNQskm3fBtGGOiSriGwF/kAsajRiGhVw==", + "dependencies": { + "@codemirror/gutter": "^0.19.0", + "@codemirror/language": "^0.19.0", + "@codemirror/rangeset": "^0.19.0", + "@codemirror/state": "^0.19.0", + "@codemirror/view": "^0.19.22" + } + }, + "node_modules/@codemirror/gutter": { + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@codemirror/gutter/-/gutter-0.19.9.tgz", + "integrity": "sha512-PFrtmilahin1g6uL27aG5tM/rqR9DZzZYZsIrCXA5Uc2OFTFqx4owuhoU9hqfYxHp5ovfvBwQ+txFzqS4vog6Q==", + "dependencies": { + "@codemirror/rangeset": "^0.19.0", + "@codemirror/state": "^0.19.0", + "@codemirror/view": "^0.19.23" + } + }, + "node_modules/@codemirror/highlight": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@codemirror/highlight/-/highlight-0.19.8.tgz", + "integrity": "sha512-v/lzuHjrYR8MN2mEJcUD6fHSTXXli9C1XGYpr+ElV6fLBIUhMTNKR3qThp611xuWfXfwDxeL7ppcbkM/MzPV3A==", + "dependencies": { + "@codemirror/language": "^0.19.0", + "@codemirror/rangeset": "^0.19.0", + "@codemirror/state": "^0.19.3", + "@codemirror/view": "^0.19.39", + "@lezer/common": "^0.15.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/history": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@codemirror/history/-/history-0.19.2.tgz", + "integrity": "sha512-unhP4t3N2smzmHoo/Yio6ueWi+il8gm9VKrvi6wlcdGH5fOfVDNkmjHQ495SiR+EdOG35+3iNebSPYww0vN7ow==", + "dependencies": { + "@codemirror/state": "^0.19.2", + "@codemirror/view": "^0.19.0" + } + }, + "node_modules/@codemirror/lang-javascript": { + "version": "0.19.7", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-0.19.7.tgz", + "integrity": "sha512-DL9f3JLqOEHH9cIwEqqjnP5bkjdVXeECksLtV+/MbPm+l4H+AG+PkwZaJQ2oR1GfPZKh8MVSIE94aGWNkJP8WQ==", + "dependencies": { + "@codemirror/autocomplete": "^0.19.0", + "@codemirror/highlight": "^0.19.7", + "@codemirror/language": "^0.19.0", + "@codemirror/lint": "^0.19.0", + "@codemirror/state": "^0.19.0", + "@codemirror/view": "^0.19.0", + "@lezer/javascript": "^0.15.1" + } + }, + "node_modules/@codemirror/language": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-0.19.10.tgz", + "integrity": "sha512-yA0DZ3RYn2CqAAGW62VrU8c4YxscMQn45y/I9sjBlqB1e2OTQLg4CCkMBuMSLXk4xaqjlsgazeOQWaJQOKfV8Q==", + "dependencies": { + "@codemirror/state": "^0.19.0", + "@codemirror/text": "^0.19.0", + "@codemirror/view": "^0.19.0", + "@lezer/common": "^0.15.5", + "@lezer/lr": "^0.15.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-0.19.6.tgz", + "integrity": "sha512-Pbw1Y5kHVs2J+itQ0uez3dI4qY9ApYVap7eNfV81x1/3/BXgBkKfadaw0gqJ4h4FDG7OnJwb0VbPsjJQllHjaA==", + "dependencies": { + "@codemirror/gutter": "^0.19.4", + "@codemirror/panel": "^0.19.0", + "@codemirror/rangeset": "^0.19.1", + "@codemirror/state": "^0.19.4", + "@codemirror/tooltip": "^0.19.16", + "@codemirror/view": "^0.19.22", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/matchbrackets": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@codemirror/matchbrackets/-/matchbrackets-0.19.4.tgz", + "integrity": "sha512-VFkaOKPNudAA5sGP1zikRHCEKU0hjYmkKpr04pybUpQvfTvNJXlReCyP0rvH/1iEwAGPL990ZTT+QrLdu4MeEA==", + "dependencies": { + "@codemirror/language": "^0.19.0", + "@codemirror/state": "^0.19.0", + "@codemirror/view": "^0.19.0", + "@lezer/common": "^0.15.0" + } + }, + "node_modules/@codemirror/panel": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@codemirror/panel/-/panel-0.19.1.tgz", + "integrity": "sha512-sYeOCMA3KRYxZYJYn5PNlt9yNsjy3zTNTrbYSfVgjgL9QomIVgOJWPO5hZ2sTN8lufO6lw0vTBsIPL9MSidmBg==", + "dependencies": { + "@codemirror/state": "^0.19.0", + "@codemirror/view": "^0.19.0" + } + }, + "node_modules/@codemirror/rangeset": { + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@codemirror/rangeset/-/rangeset-0.19.9.tgz", + "integrity": "sha512-V8YUuOvK+ew87Xem+71nKcqu1SXd5QROMRLMS/ljT5/3MCxtgrRie1Cvild0G/Z2f1fpWxzX78V0U4jjXBorBQ==", + "dependencies": { + "@codemirror/state": "^0.19.0" + } + }, + "node_modules/@codemirror/rectangular-selection": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@codemirror/rectangular-selection/-/rectangular-selection-0.19.2.tgz", + "integrity": "sha512-AXK/p5eGwFJ9GJcLfntqN4dgY+XiIF7eHfXNQJX5HhQLSped2wJE6WuC1rMEaOlcpOqlb9mrNi/ZdUjSIj9mbA==", + "dependencies": { + "@codemirror/state": "^0.19.0", + "@codemirror/text": "^0.19.4", + "@codemirror/view": "^0.19.48" + } + }, + "node_modules/@codemirror/search": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-0.19.10.tgz", + "integrity": "sha512-qjubm69HJixPBWzI6HeEghTWOOD8NXiHOTRNvdizqs8xWRuFChq9zkjD3XiAJ7GXSTzCuQJnAP9DBBGCLq4ZIA==", + "dependencies": { + "@codemirror/panel": "^0.19.0", + "@codemirror/rangeset": "^0.19.0", + "@codemirror/state": "^0.19.3", + "@codemirror/text": "^0.19.0", + "@codemirror/view": "^0.19.34", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-0.19.9.tgz", + "integrity": "sha512-psOzDolKTZkx4CgUqhBQ8T8gBc0xN5z4gzed109aF6x7D7umpDRoimacI/O6d9UGuyl4eYuDCZmDFr2Rq7aGOw==", + "dependencies": { + "@codemirror/text": "^0.19.0" + } + }, + "node_modules/@codemirror/text": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@codemirror/text/-/text-0.19.6.tgz", + "integrity": "sha512-T9jnREMIygx+TPC1bOuepz18maGq/92q2a+n4qTqObKwvNMg+8cMTslb8yxeEDEq7S3kpgGWxgO1UWbQRij0dA==" + }, + "node_modules/@codemirror/tooltip": { + "version": "0.19.16", + "resolved": "https://registry.npmjs.org/@codemirror/tooltip/-/tooltip-0.19.16.tgz", + "integrity": "sha512-zxKDHryUV5/RS45AQL+wOeN+i7/l81wK56OMnUPoTSzCWNITfxHn7BToDsjtrRKbzHqUxKYmBnn/4hPjpZ4WJQ==", + "dependencies": { + "@codemirror/state": "^0.19.0", + "@codemirror/view": "^0.19.0" + } + }, + "node_modules/@codemirror/view": { + "version": "0.19.48", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-0.19.48.tgz", + "integrity": "sha512-0eg7D2Nz4S8/caetCTz61rK0tkHI17V/d15Jy0kLOT8dTLGGNJUponDnW28h2B6bERmPlVHKh8MJIr5OCp1nGw==", + "dependencies": { + "@codemirror/rangeset": "^0.19.5", + "@codemirror/state": "^0.19.3", + "@codemirror/text": "^0.19.0", + "style-mod": "^4.0.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@csstools/normalize.css": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.0.0.tgz", @@ -2729,6 +2949,27 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@lezer/common": { + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.12.tgz", + "integrity": "sha512-edfwCxNLnzq5pBA/yaIhwJ3U3Kz8VAUOTRg0hhxaizaI1N+qxV7EXDv/kLCkLeq2RzSFvxexlaj5Mzfn2kY0Ig==" + }, + "node_modules/@lezer/javascript": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-0.15.3.tgz", + "integrity": "sha512-8jA2NpOfpWwSPZxRhd9BxK2ZPvGd7nLE3LFTJ5AbMhXAzMHeMjneV6GEVd7dAIee85dtap0jdb6bgOSO0+lfwA==", + "dependencies": { + "@lezer/lr": "^0.15.0" + } + }, + "node_modules/@lezer/lr": { + "version": "0.15.8", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.15.8.tgz", + "integrity": "sha512-bM6oE6VQZ6hIFxDNKk8bKPa14hqFrV07J/vHGOeiAbJReIaQXmkVb6xQu4MR+JBTLa5arGRyAAjJe1qaQt3Uvg==", + "dependencies": { + "@lezer/common": "^0.15.0" + } + }, "node_modules/@mdx-js/mdx": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", @@ -7575,6 +7816,16 @@ "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.2.tgz", "integrity": "sha512-SZM4Zq7XEC8Fhroqe3LxbEEX1zUPWH1wMr5zxiBuiUF64iYOUH/JI88v4tBag8MiBS8B8gRv8O1pPXGYXQ4ErA==" }, + "node_modules/codemirror6-themes": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/codemirror6-themes/-/codemirror6-themes-0.1.2.tgz", + "integrity": "sha512-MlXaa3Bx3iz4Bh9DK7+Xy+aPqbRHRsPG1iogoe6W/5f6JJqTER5QroZfKTz+ACfTqpjk2OHahv6XMl8KRi6h0w==", + "dependencies": { + "@codemirror/highlight": "^0.19.0", + "@codemirror/state": "^0.19.0", + "@codemirror/view": "^0.19.0" + } + }, "node_modules/collapse-white-space": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", @@ -7839,6 +8090,11 @@ "node": ">=10" } }, + "node_modules/crelt": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz", + "integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==" + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -16443,6 +16699,33 @@ "react": ">=15.5 <=16.x" } }, + "node_modules/react-codemirror6": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/react-codemirror6/-/react-codemirror6-1.1.0.tgz", + "integrity": "sha512-xoXBMrnD4ZikGc3pJSXvjcy8HXuFHMOID1CTf3oJZzfh25MtkLaJxSd3gBz/hqy3rqlGXJH3BMVYDsFsfnHwQQ==", + "dependencies": { + "@babel/runtime": "^7.14.8", + "@codemirror/autocomplete": "^0.19.15", + "@codemirror/closebrackets": "^0.19.1", + "@codemirror/commands": "^0.19.8", + "@codemirror/comment": "^0.19.1", + "@codemirror/fold": "^0.19.3", + "@codemirror/gutter": "^0.19.9", + "@codemirror/highlight": "^0.19.8", + "@codemirror/history": "^0.19.2", + "@codemirror/language": "^0.19.10", + "@codemirror/lint": "^0.19.6", + "@codemirror/matchbrackets": "^0.19.4", + "@codemirror/rectangular-selection": "^0.19.2", + "@codemirror/search": "^0.19.9", + "@codemirror/state": "^0.19.9", + "@codemirror/view": "^0.19.48" + }, + "peerDependencies": { + "react": "^17.0.2", + "react-dom": "^17.0.2" + } + }, "node_modules/react-dev-utils": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz", @@ -18095,6 +18378,11 @@ "webpack": "^5.0.0" } }, + "node_modules/style-mod": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz", + "integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==" + }, "node_modules/style-to-object": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", @@ -19148,6 +19436,11 @@ "browser-process-hrtime": "^1.0.0" } }, + "node_modules/w3c-keyname": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz", + "integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw==" + }, "node_modules/w3c-xmlserializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", @@ -21343,6 +21636,223 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, + "@codemirror/autocomplete": { + "version": "0.19.15", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-0.19.15.tgz", + "integrity": "sha512-GQWzvvuXxNUyaEk+5gawbAD8s51/v2Chb++nx0e2eGWrphWk42isBtzOMdc3DxrxrZtPZ55q2ldNp+6G8KJLIQ==", + "requires": { + "@codemirror/language": "^0.19.0", + "@codemirror/state": "^0.19.4", + "@codemirror/text": "^0.19.2", + "@codemirror/tooltip": "^0.19.12", + "@codemirror/view": "^0.19.0", + "@lezer/common": "^0.15.0" + } + }, + "@codemirror/closebrackets": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@codemirror/closebrackets/-/closebrackets-0.19.2.tgz", + "integrity": "sha512-ClMPzPcPP0eQiDcVjtVPl6OLxgdtZSYDazsvT0AKl70V1OJva0eHgl4/6kCW3RZ0pb2n34i9nJz4eXCmK+TYDA==", + "requires": { + "@codemirror/language": "^0.19.0", + "@codemirror/rangeset": "^0.19.0", + "@codemirror/state": "^0.19.2", + "@codemirror/text": "^0.19.0", + "@codemirror/view": "^0.19.44" + } + }, + "@codemirror/commands": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-0.19.8.tgz", + "integrity": "sha512-65LIMSGUGGpY3oH6mzV46YWRrgao6NmfJ+AuC7jNz3K5NPnH6GCV1H5I6SwOFyVbkiygGyd0EFwrWqywTBD1aw==", + "requires": { + "@codemirror/language": "^0.19.0", + "@codemirror/matchbrackets": "^0.19.0", + "@codemirror/state": "^0.19.2", + "@codemirror/text": "^0.19.6", + "@codemirror/view": "^0.19.22", + "@lezer/common": "^0.15.0" + } + }, + "@codemirror/comment": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@codemirror/comment/-/comment-0.19.1.tgz", + "integrity": "sha512-uGKteBuVWAC6fW+Yt8u27DOnXMT/xV4Ekk2Z5mRsiADCZDqYvryrJd6PLL5+8t64BVyocwQwNfz1UswYS2CtFQ==", + "requires": { + "@codemirror/state": "^0.19.9", + "@codemirror/text": "^0.19.0", + "@codemirror/view": "^0.19.0" + } + }, + "@codemirror/fold": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@codemirror/fold/-/fold-0.19.4.tgz", + "integrity": "sha512-0SNSkRSOa6gymD6GauHa3sxiysjPhUC0SRVyTlvL52o0gz9GHdc8kNqNQskm3fBtGGOiSriGwF/kAsajRiGhVw==", + "requires": { + "@codemirror/gutter": "^0.19.0", + "@codemirror/language": "^0.19.0", + "@codemirror/rangeset": "^0.19.0", + "@codemirror/state": "^0.19.0", + "@codemirror/view": "^0.19.22" + } + }, + "@codemirror/gutter": { + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@codemirror/gutter/-/gutter-0.19.9.tgz", + "integrity": "sha512-PFrtmilahin1g6uL27aG5tM/rqR9DZzZYZsIrCXA5Uc2OFTFqx4owuhoU9hqfYxHp5ovfvBwQ+txFzqS4vog6Q==", + "requires": { + "@codemirror/rangeset": "^0.19.0", + "@codemirror/state": "^0.19.0", + "@codemirror/view": "^0.19.23" + } + }, + "@codemirror/highlight": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@codemirror/highlight/-/highlight-0.19.8.tgz", + "integrity": "sha512-v/lzuHjrYR8MN2mEJcUD6fHSTXXli9C1XGYpr+ElV6fLBIUhMTNKR3qThp611xuWfXfwDxeL7ppcbkM/MzPV3A==", + "requires": { + "@codemirror/language": "^0.19.0", + "@codemirror/rangeset": "^0.19.0", + "@codemirror/state": "^0.19.3", + "@codemirror/view": "^0.19.39", + "@lezer/common": "^0.15.0", + "style-mod": "^4.0.0" + } + }, + "@codemirror/history": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@codemirror/history/-/history-0.19.2.tgz", + "integrity": "sha512-unhP4t3N2smzmHoo/Yio6ueWi+il8gm9VKrvi6wlcdGH5fOfVDNkmjHQ495SiR+EdOG35+3iNebSPYww0vN7ow==", + "requires": { + "@codemirror/state": "^0.19.2", + "@codemirror/view": "^0.19.0" + } + }, + "@codemirror/lang-javascript": { + "version": "0.19.7", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-0.19.7.tgz", + "integrity": "sha512-DL9f3JLqOEHH9cIwEqqjnP5bkjdVXeECksLtV+/MbPm+l4H+AG+PkwZaJQ2oR1GfPZKh8MVSIE94aGWNkJP8WQ==", + "requires": { + "@codemirror/autocomplete": "^0.19.0", + "@codemirror/highlight": "^0.19.7", + "@codemirror/language": "^0.19.0", + "@codemirror/lint": "^0.19.0", + "@codemirror/state": "^0.19.0", + "@codemirror/view": "^0.19.0", + "@lezer/javascript": "^0.15.1" + } + }, + "@codemirror/language": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-0.19.10.tgz", + "integrity": "sha512-yA0DZ3RYn2CqAAGW62VrU8c4YxscMQn45y/I9sjBlqB1e2OTQLg4CCkMBuMSLXk4xaqjlsgazeOQWaJQOKfV8Q==", + "requires": { + "@codemirror/state": "^0.19.0", + "@codemirror/text": "^0.19.0", + "@codemirror/view": "^0.19.0", + "@lezer/common": "^0.15.5", + "@lezer/lr": "^0.15.0" + } + }, + "@codemirror/lint": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-0.19.6.tgz", + "integrity": "sha512-Pbw1Y5kHVs2J+itQ0uez3dI4qY9ApYVap7eNfV81x1/3/BXgBkKfadaw0gqJ4h4FDG7OnJwb0VbPsjJQllHjaA==", + "requires": { + "@codemirror/gutter": "^0.19.4", + "@codemirror/panel": "^0.19.0", + "@codemirror/rangeset": "^0.19.1", + "@codemirror/state": "^0.19.4", + "@codemirror/tooltip": "^0.19.16", + "@codemirror/view": "^0.19.22", + "crelt": "^1.0.5" + } + }, + "@codemirror/matchbrackets": { + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@codemirror/matchbrackets/-/matchbrackets-0.19.4.tgz", + "integrity": "sha512-VFkaOKPNudAA5sGP1zikRHCEKU0hjYmkKpr04pybUpQvfTvNJXlReCyP0rvH/1iEwAGPL990ZTT+QrLdu4MeEA==", + "requires": { + "@codemirror/language": "^0.19.0", + "@codemirror/state": "^0.19.0", + "@codemirror/view": "^0.19.0", + "@lezer/common": "^0.15.0" + } + }, + "@codemirror/panel": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@codemirror/panel/-/panel-0.19.1.tgz", + "integrity": "sha512-sYeOCMA3KRYxZYJYn5PNlt9yNsjy3zTNTrbYSfVgjgL9QomIVgOJWPO5hZ2sTN8lufO6lw0vTBsIPL9MSidmBg==", + "requires": { + "@codemirror/state": "^0.19.0", + "@codemirror/view": "^0.19.0" + } + }, + "@codemirror/rangeset": { + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@codemirror/rangeset/-/rangeset-0.19.9.tgz", + "integrity": "sha512-V8YUuOvK+ew87Xem+71nKcqu1SXd5QROMRLMS/ljT5/3MCxtgrRie1Cvild0G/Z2f1fpWxzX78V0U4jjXBorBQ==", + "requires": { + "@codemirror/state": "^0.19.0" + } + }, + "@codemirror/rectangular-selection": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@codemirror/rectangular-selection/-/rectangular-selection-0.19.2.tgz", + "integrity": "sha512-AXK/p5eGwFJ9GJcLfntqN4dgY+XiIF7eHfXNQJX5HhQLSped2wJE6WuC1rMEaOlcpOqlb9mrNi/ZdUjSIj9mbA==", + "requires": { + "@codemirror/state": "^0.19.0", + "@codemirror/text": "^0.19.4", + "@codemirror/view": "^0.19.48" + } + }, + "@codemirror/search": { + "version": "0.19.10", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-0.19.10.tgz", + "integrity": "sha512-qjubm69HJixPBWzI6HeEghTWOOD8NXiHOTRNvdizqs8xWRuFChq9zkjD3XiAJ7GXSTzCuQJnAP9DBBGCLq4ZIA==", + "requires": { + "@codemirror/panel": "^0.19.0", + "@codemirror/rangeset": "^0.19.0", + "@codemirror/state": "^0.19.3", + "@codemirror/text": "^0.19.0", + "@codemirror/view": "^0.19.34", + "crelt": "^1.0.5" + } + }, + "@codemirror/state": { + "version": "0.19.9", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-0.19.9.tgz", + "integrity": "sha512-psOzDolKTZkx4CgUqhBQ8T8gBc0xN5z4gzed109aF6x7D7umpDRoimacI/O6d9UGuyl4eYuDCZmDFr2Rq7aGOw==", + "requires": { + "@codemirror/text": "^0.19.0" + } + }, + "@codemirror/text": { + "version": "0.19.6", + "resolved": "https://registry.npmjs.org/@codemirror/text/-/text-0.19.6.tgz", + "integrity": "sha512-T9jnREMIygx+TPC1bOuepz18maGq/92q2a+n4qTqObKwvNMg+8cMTslb8yxeEDEq7S3kpgGWxgO1UWbQRij0dA==" + }, + "@codemirror/tooltip": { + "version": "0.19.16", + "resolved": "https://registry.npmjs.org/@codemirror/tooltip/-/tooltip-0.19.16.tgz", + "integrity": "sha512-zxKDHryUV5/RS45AQL+wOeN+i7/l81wK56OMnUPoTSzCWNITfxHn7BToDsjtrRKbzHqUxKYmBnn/4hPjpZ4WJQ==", + "requires": { + "@codemirror/state": "^0.19.0", + "@codemirror/view": "^0.19.0" + } + }, + "@codemirror/view": { + "version": "0.19.48", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-0.19.48.tgz", + "integrity": "sha512-0eg7D2Nz4S8/caetCTz61rK0tkHI17V/d15Jy0kLOT8dTLGGNJUponDnW28h2B6bERmPlVHKh8MJIr5OCp1nGw==", + "requires": { + "@codemirror/rangeset": "^0.19.5", + "@codemirror/state": "^0.19.3", + "@codemirror/text": "^0.19.0", + "style-mod": "^4.0.0", + "w3c-keyname": "^2.2.4" + } + }, "@csstools/normalize.css": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.0.0.tgz", @@ -21972,6 +22482,27 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "@lezer/common": { + "version": "0.15.12", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.12.tgz", + "integrity": "sha512-edfwCxNLnzq5pBA/yaIhwJ3U3Kz8VAUOTRg0hhxaizaI1N+qxV7EXDv/kLCkLeq2RzSFvxexlaj5Mzfn2kY0Ig==" + }, + "@lezer/javascript": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-0.15.3.tgz", + "integrity": "sha512-8jA2NpOfpWwSPZxRhd9BxK2ZPvGd7nLE3LFTJ5AbMhXAzMHeMjneV6GEVd7dAIee85dtap0jdb6bgOSO0+lfwA==", + "requires": { + "@lezer/lr": "^0.15.0" + } + }, + "@lezer/lr": { + "version": "0.15.8", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.15.8.tgz", + "integrity": "sha512-bM6oE6VQZ6hIFxDNKk8bKPa14hqFrV07J/vHGOeiAbJReIaQXmkVb6xQu4MR+JBTLa5arGRyAAjJe1qaQt3Uvg==", + "requires": { + "@lezer/common": "^0.15.0" + } + }, "@mdx-js/mdx": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", @@ -25359,6 +25890,16 @@ "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.2.tgz", "integrity": "sha512-SZM4Zq7XEC8Fhroqe3LxbEEX1zUPWH1wMr5zxiBuiUF64iYOUH/JI88v4tBag8MiBS8B8gRv8O1pPXGYXQ4ErA==" }, + "codemirror6-themes": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/codemirror6-themes/-/codemirror6-themes-0.1.2.tgz", + "integrity": "sha512-MlXaa3Bx3iz4Bh9DK7+Xy+aPqbRHRsPG1iogoe6W/5f6JJqTER5QroZfKTz+ACfTqpjk2OHahv6XMl8KRi6h0w==", + "requires": { + "@codemirror/highlight": "^0.19.0", + "@codemirror/state": "^0.19.0", + "@codemirror/view": "^0.19.0" + } + }, "collapse-white-space": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", @@ -25560,6 +26101,11 @@ "yaml": "^1.10.0" } }, + "crelt": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz", + "integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==" + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -31647,6 +32193,29 @@ "integrity": "sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==", "requires": {} }, + "react-codemirror6": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/react-codemirror6/-/react-codemirror6-1.1.0.tgz", + "integrity": "sha512-xoXBMrnD4ZikGc3pJSXvjcy8HXuFHMOID1CTf3oJZzfh25MtkLaJxSd3gBz/hqy3rqlGXJH3BMVYDsFsfnHwQQ==", + "requires": { + "@babel/runtime": "^7.14.8", + "@codemirror/autocomplete": "^0.19.15", + "@codemirror/closebrackets": "^0.19.1", + "@codemirror/commands": "^0.19.8", + "@codemirror/comment": "^0.19.1", + "@codemirror/fold": "^0.19.3", + "@codemirror/gutter": "^0.19.9", + "@codemirror/highlight": "^0.19.8", + "@codemirror/history": "^0.19.2", + "@codemirror/language": "^0.19.10", + "@codemirror/lint": "^0.19.6", + "@codemirror/matchbrackets": "^0.19.4", + "@codemirror/rectangular-selection": "^0.19.2", + "@codemirror/search": "^0.19.9", + "@codemirror/state": "^0.19.9", + "@codemirror/view": "^0.19.48" + } + }, "react-dev-utils": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz", @@ -32899,6 +33468,11 @@ "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", "requires": {} }, + "style-mod": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz", + "integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==" + }, "style-to-object": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", @@ -33677,6 +34251,11 @@ "browser-process-hrtime": "^1.0.0" } }, + "w3c-keyname": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz", + "integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw==" + }, "w3c-xmlserializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", diff --git a/repl/package.json b/repl/package.json index 58a65c61..f4e3a9a8 100644 --- a/repl/package.json +++ b/repl/package.json @@ -4,14 +4,17 @@ "private": true, "homepage": "https://strudel.tidalcycles.org", "dependencies": { + "@codemirror/lang-javascript": "^0.19.0", "@testing-library/jest-dom": "^5.16.3", "@testing-library/react": "^12.1.4", "@testing-library/user-event": "^13.5.0", "codemirror": "^5.65.2", + "codemirror6-themes": "^0.1.2", "events": "^3.3.0", "gh-pages": "^3.2.3", "react": "^17.0.2", "react-codemirror2": "^7.2.1", + "react-codemirror6": "^1.1.0", "react-dom": "^17.0.2", "react-scripts": "5.0.0", "tone": "^14.7.77", diff --git a/repl/src/App.js b/repl/src/App.js index 6c85dc39..9f0e759b 100644 --- a/repl/src/App.js +++ b/repl/src/App.js @@ -1,5 +1,6 @@ -import React, { useCallback, useLayoutEffect, useRef, useState } from 'react'; -import CodeMirror, { markEvent, markParens } from './CodeMirror'; +import React, { useCallback, useLayoutEffect, useRef, useState, useEffect } from 'react'; +// import CodeMirror, { markEvent, markParens } from './CodeMirror'; +import CodeMirror6, { highlightEvent } from './CodeMirror6'; import cx from './cx'; import logo from './logo.svg'; import playStatic from './static.mjs'; @@ -70,13 +71,32 @@ const randomTune = getRandomTune(); const defaultSynth = getDefaultSynth(); function App() { - const [editor, setEditor] = useState(); - const { setCode, setPattern, error, code, cycle, dirty, log, togglePlay, activateCode, pattern, pushLog, pending } = - useRepl({ - tune: decoded || randomTune, - defaultSynth, - onDraw: useCallback((time, event) => markEvent(editor)(time, event), [editor]), - }); + // const [editor, setEditor] = useState(); + const [view, setView] = useState(); + const [codeToHighlight, setCodeToHighlight] = useState(); + const { + setCode, + setPattern, + error, + code, + cycle, + dirty, + log, + togglePlay, + activeCode, + activateCode, + pattern, + pushLog, + pending, + } = useRepl({ + tune: decoded || randomTune, + defaultSynth, + // onDraw: useCallback((time, event) => markEvent(editor)(time, event), [editor]), + onDraw: useCallback((_, e) => highlightEvent(e, view, codeToHighlight), [view, codeToHighlight]), + }); + useEffect(() => { + setCodeToHighlight(activeCode); + }, [activeCode]); const [uiHidden, setUiHidden] = useState(false); const logBox = useRef(); // scroll log box to bottom when log changes @@ -179,19 +199,13 @@ function App() { - + {/* */}
-
-
- + + {/* setCode(value)} - /> - - {!cycle.started ? `press ctrl+enter to play\n` : dirty ? `ctrl+enter to update\n` : 'no changes\n'} - -
+ /> */} + + {!cycle.started ? `press ctrl+enter to play\n` : dirty ? `ctrl+enter to update\n` : 'no changes\n'} + {error && (
{error?.message || 'unknown error'} diff --git a/repl/src/CodeMirror6.jsx b/repl/src/CodeMirror6.jsx new file mode 100644 index 00000000..24b1899b --- /dev/null +++ b/repl/src/CodeMirror6.jsx @@ -0,0 +1,188 @@ +import React from 'react'; +import { CodeMirror as _CodeMirror } from 'react-codemirror6'; +import { EditorView, Decoration } from '@codemirror/view'; +import { StateField, StateEffect } from '@codemirror/state'; +import { javascript } from '@codemirror/lang-javascript'; +import { materialPalenight } from 'codemirror6-themes'; + +// EditorView.theme(materialPalenight); + +const highlightMark = Decoration.mark({ class: 'cm-highlight' }); +const addHighlight = StateEffect.define(); +const removeHighlight = StateEffect.define(); +const highlightTheme = EditorView.baseTheme({ + '.cm-highlight': { outline: '1px solid #FFCA28' }, + // '.cm-highlight': { background: '#FFCA28' }, +}); +const highlightField = StateField.define({ + create() { + return Decoration.none; + }, + update(highlights, tr) { + highlights = highlights.map(tr.changes); + for (let e of tr.effects) { + if (e.is(addHighlight)) { + highlights = highlights.update({ + add: [highlightMark.range(e.value.from, e.value.to)], + }); + } + if (e.is(removeHighlight)) { + highlights = highlights.update({ + filter: (f, t, value) => { + if (f === e.value.from && t === e.value.to) { + return false; + } + return true; + // console.log('filter', f,t,value, e.value.from, e.value.to); + }, + }); + } + } + return highlights; + }, + provide: (f) => EditorView.decorations.from(f), +}); + +// let timeouts = []; + +export const highlightEvent = (event, view, code) => { + if (!view) { + return; + } + const ranges = event.context?.locations?.map(({ start, end }) => { + return [start, end].map(({ line, column }) => positionToOffset({ line: line - 1, ch: column }, code)); + }); + const effects = ranges.map(([from, to]) => addHighlight.of({ from, to })); + + if (!effects.length) return false; + if (!view.state.field(highlightField, false)) { + effects.push(StateEffect.appendConfig.of([highlightField, highlightTheme])); + } + view.dispatch({ effects }); + // const index = timeouts.length; + // timeouts = timeouts.filter(time) + /* const timeout = */ setTimeout(() => { + const effects = ranges.map(([from, to]) => removeHighlight.of({ from, to })); + view.dispatch({ effects }); + // timeouts.splice(index, 1); + }, event.duration * 1000); + // timeouts.pusn({timeout,); +}; + +export default function CodeMirror({ value, onChange, onViewChanged, onCursor, options, editorDidMount }) { + return ( + <> + <_CodeMirror + onViewChange={onViewChanged} + style={{ + display: 'flex', + flexDirection: 'column', + flex: '1 0 auto', + }} + value={value} + onChange={onChange} + extensions={[ + javascript(), + materialPalenight + // theme, language, ... + ]} + /> + + ); +} + +let parenMark; +export const markParens = (editor, data) => { + const v = editor.getDoc().getValue(); + const marked = getCurrentParenArea(v, data); + parenMark?.clear(); + parenMark = editor.getDoc().markText(...marked, { css: 'background-color: #00007720' }); // +}; + +// returns { line, ch } from absolute character offset +export function offsetToPosition(offset, code) { + const lines = code.split('\n'); + let line = 0; + let ch = 0; + for (let i = 0; i < offset; i++) { + if (ch === lines[line].length) { + line++; + ch = 0; + } else { + ch++; + } + } + return { line, ch }; +} + +// returns absolute character offset from { line, ch } +export function positionToOffset(position, code) { + const lines = code.split('\n'); + let offset = 0; + for (let i = 0; i < position.line; i++) { + offset += lines[i].length + 1; + } + offset += position.ch; + return offset; +} + +// given code and caret position, the functions returns the indices of the parens we are in +export function getCurrentParenArea(code, caretPosition) { + const caret = positionToOffset(caretPosition, code); + let open, i, begin, end; + // walk left + i = caret; + open = 0; + while (i > 0) { + if (code[i - 1] === '(') { + open--; + } else if (code[i - 1] === ')') { + open++; + } + if (open === -1) { + break; + } + i--; + } + begin = i; + // walk right + i = caret; + open = 0; + while (i < code.length) { + if (code[i] === '(') { + open--; + } else if (code[i] === ')') { + open++; + } + if (open === 1) { + break; + } + i++; + } + end = i; + return [begin, end].map((o) => offsetToPosition(o, code)); +} + +/* +export const markEvent = (editor) => (time, event) => { + const locs = event.context.locations; + if (!locs || !editor) { + return; + } + const col = event.context?.color || '#FFCA28'; + // mark active event + const marks = locs.map(({ start, end }) => + editor.getDoc().markText( + { line: start.line - 1, ch: start.column }, + { line: end.line - 1, ch: end.column }, + //{ css: 'background-color: #FFCA28; color: black' } // background-color is now used by parent marking + { css: 'outline: 1px solid ' + col + '; box-sizing:border-box' }, + //{ css: `background-color: ${col};border-radius:5px` }, + ), + ); + //Tone.Transport.schedule(() => { // problem: this can be cleared by scheduler... + setTimeout(() => { + marks.forEach((mark) => mark.clear()); + // }, '+' + event.duration * 0.5); + }, event.duration * 1000); +}; */ From 10487683d399caadc41912249ae29e3843ad51be Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Mon, 25 Apr 2022 20:46:12 +0200 Subject: [PATCH 02/16] tiny bit of style --- repl/src/App.js | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/repl/src/App.js b/repl/src/App.js index 9f0e759b..1c574e6e 100644 --- a/repl/src/App.js +++ b/repl/src/App.js @@ -1,5 +1,4 @@ import React, { useCallback, useLayoutEffect, useRef, useState, useEffect } from 'react'; -// import CodeMirror, { markEvent, markParens } from './CodeMirror'; import CodeMirror6, { highlightEvent } from './CodeMirror6'; import cx from './cx'; import logo from './logo.svg'; @@ -51,7 +50,6 @@ extend( Tone, }, ); -// eval stuff end const codeParam = window.location.href.split('#')[1]; let decoded; @@ -149,15 +147,15 @@ function App() { id="header" className={cx( 'flex-none w-full h-14 px-2 flex border-b border-gray-200 justify-between z-[10]', - uiHidden ? 'bg-transparent text-white' : 'bg-white', + uiHidden ? 'bg-transparent text-white' : 'bg-gray-100', )} >
- logo -

Strudel REPL

+ logo +

Strudel REPL

-
- - - {/* */}
+ {/* onCursor={markParens} */} - {/* setCode(value)} - /> */} {!cycle.started ? `press ctrl+enter to play\n` : dirty ? `ctrl+enter to update\n` : 'no changes\n'} From 5dea15ade9356d691b20808dfa47b4ceb002326a Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Mon, 25 Apr 2022 21:25:13 +0200 Subject: [PATCH 03/16] remove background color from cm6 theme --- repl/src/CodeMirror6.jsx | 7 +- repl/src/themes/material-palenight.js | 130 ++++++++++++++++++++++++++ repl/src/tutorial/style.css | 4 + 3 files changed, 137 insertions(+), 4 deletions(-) create mode 100644 repl/src/themes/material-palenight.js diff --git a/repl/src/CodeMirror6.jsx b/repl/src/CodeMirror6.jsx index 24b1899b..341ed0df 100644 --- a/repl/src/CodeMirror6.jsx +++ b/repl/src/CodeMirror6.jsx @@ -3,9 +3,8 @@ import { CodeMirror as _CodeMirror } from 'react-codemirror6'; import { EditorView, Decoration } from '@codemirror/view'; import { StateField, StateEffect } from '@codemirror/state'; import { javascript } from '@codemirror/lang-javascript'; -import { materialPalenight } from 'codemirror6-themes'; - -// EditorView.theme(materialPalenight); +// import { materialPalenight } from 'codemirror6-themes'; +import { materialPalenight } from './themes/material-palenight'; const highlightMark = Decoration.mark({ class: 'cm-highlight' }); const addHighlight = StateEffect.define(); @@ -83,7 +82,7 @@ export default function CodeMirror({ value, onChange, onViewChanged, onCursor, o onChange={onChange} extensions={[ javascript(), - materialPalenight + materialPalenight, // theme, language, ... ]} /> diff --git a/repl/src/themes/material-palenight.js b/repl/src/themes/material-palenight.js new file mode 100644 index 00000000..d50e10c7 --- /dev/null +++ b/repl/src/themes/material-palenight.js @@ -0,0 +1,130 @@ +import { EditorView } from '@codemirror/view'; +import { HighlightStyle, tags as t } from '@codemirror/highlight'; + +/* + Credits for color palette: + + Author: Mattia Astorino (http://github.com/equinusocio) + Website: https://material-theme.site/ +*/ + +const ivory = '#abb2bf', + stone = '#7d8799', // Brightened compared to original to increase contrast + invalid = '#ffffff', + darkBackground = '#21252b', + highlightBackground = 'rgba(0, 0, 0, 0.5)', + // background = '#292d3e', + background = 'transparent', + tooltipBackground = '#353a42', + selection = 'rgba(128, 203, 196, 0.2)', + cursor = '#ffcc00'; + +/// The editor theme styles for Material Palenight. +export const materialPalenightTheme = EditorView.theme( + { + // done + '&': { + color: '#ffffff', + backgroundColor: background, + }, + + // done + '.cm-content': { + caretColor: cursor, + }, + + // done + '&.cm-focused .cm-cursor': { + borderLeftColor: cursor, + }, + + '&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': { + backgroundColor: selection, + }, + + '.cm-panels': { backgroundColor: darkBackground, color: '#ffffff' }, + '.cm-panels.cm-panels-top': { borderBottom: '2px solid black' }, + '.cm-panels.cm-panels-bottom': { borderTop: '2px solid black' }, + + // done, use onedarktheme + '.cm-searchMatch': { + backgroundColor: '#72a1ff59', + outline: '1px solid #457dff', + }, + '.cm-searchMatch.cm-searchMatch-selected': { + backgroundColor: '#6199ff2f', + }, + + '.cm-activeLine': { backgroundColor: highlightBackground }, + '.cm-selectionMatch': { backgroundColor: '#aafe661a' }, + + '&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': { + backgroundColor: '#bad0f847', + outline: '1px solid #515a6b', + }, + + // done + '.cm-gutters': { + background, + color: '#676e95', + border: 'none', + }, + + '.cm-activeLineGutter': { + backgroundColor: highlightBackground, + }, + + '.cm-foldPlaceholder': { + backgroundColor: 'transparent', + border: 'none', + color: '#ddd', + }, + + '.cm-tooltip': { + border: 'none', + backgroundColor: tooltipBackground, + }, + '.cm-tooltip .cm-tooltip-arrow:before': { + borderTopColor: 'transparent', + borderBottomColor: 'transparent', + }, + '.cm-tooltip .cm-tooltip-arrow:after': { + borderTopColor: tooltipBackground, + borderBottomColor: tooltipBackground, + }, + '.cm-tooltip-autocomplete': { + '& > ul > li[aria-selected]': { + backgroundColor: highlightBackground, + color: ivory, + }, + }, + }, + { dark: true }, +); + +/// The highlighting style for code in the Material Palenight theme. +export const materialPalenightHighlightStyle = HighlightStyle.define([ + { tag: t.keyword, color: '#c792ea' }, + { tag: t.operator, color: '#89ddff' }, + { tag: t.special(t.variableName), color: '#eeffff' }, + { tag: t.typeName, color: '#f07178' }, + { tag: t.atom, color: '#f78c6c' }, + { tag: t.number, color: '#ff5370' }, + { tag: t.definition(t.variableName), color: '#82aaff' }, + { tag: t.string, color: '#c3e88d' }, + { tag: t.special(t.string), color: '#f07178' }, + { tag: t.comment, color: stone }, + { tag: t.variableName, color: '#f07178' }, + { tag: t.tagName, color: '#ff5370' }, + { tag: t.bracket, color: '#a2a1a4' }, + { tag: t.meta, color: '#ffcb6b' }, + { tag: t.attributeName, color: '#c792ea' }, + { tag: t.propertyName, color: '#c792ea' }, + { tag: t.className, color: '#decb6b' }, + { tag: t.invalid, color: invalid }, +]); + +/// Extension to enable the Material Palenight theme (both the editor theme and +/// the highlight style). +// : Extension +export const materialPalenight = [materialPalenightTheme, materialPalenightHighlightStyle]; diff --git a/repl/src/tutorial/style.css b/repl/src/tutorial/style.css index 2a2e1d06..589ee893 100644 --- a/repl/src/tutorial/style.css +++ b/repl/src/tutorial/style.css @@ -8,6 +8,10 @@ height: inherit !important; } +.cm-editor { + background-color: transparent !important; +} + main { margin: 0 auto; } From 5aed046b3489f46cdef1ff371d883c41c4b4f799 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Mon, 25 Apr 2022 21:32:25 +0200 Subject: [PATCH 04/16] fix z-index --- repl/src/themes/material-palenight.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/repl/src/themes/material-palenight.js b/repl/src/themes/material-palenight.js index d50e10c7..be7527c1 100644 --- a/repl/src/themes/material-palenight.js +++ b/repl/src/themes/material-palenight.js @@ -26,13 +26,16 @@ export const materialPalenightTheme = EditorView.theme( '&': { color: '#ffffff', backgroundColor: background, + 'z-index': 11, }, // done '.cm-content': { caretColor: cursor, }, - + '.cm-line > *': { + background: '#00000070', + }, // done '&.cm-focused .cm-cursor': { borderLeftColor: cursor, From 069fff673a58b4df2173b968f9d56ce3af26d16d Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Mon, 25 Apr 2022 22:00:18 +0200 Subject: [PATCH 05/16] fix some bugs --- repl/src/App.js | 9 +++--- repl/src/CodeMirror6.jsx | 45 ++++++++++++++++----------- repl/src/themes/material-palenight.js | 7 +++-- repl/src/useRepl.mjs | 11 ++++--- 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/repl/src/App.js b/repl/src/App.js index 1c574e6e..ffd0a27a 100644 --- a/repl/src/App.js +++ b/repl/src/App.js @@ -82,6 +82,7 @@ function App() { log, togglePlay, activeCode, + setActiveCode, activateCode, pattern, pushLog, @@ -90,11 +91,8 @@ function App() { tune: decoded || randomTune, defaultSynth, // onDraw: useCallback((time, event) => markEvent(editor)(time, event), [editor]), - onDraw: useCallback((_, e) => highlightEvent(e, view, codeToHighlight), [view, codeToHighlight]), + onDraw: useCallback((_, e, code) => code && highlightEvent(e, view, code), [view]), }); - useEffect(() => { - setCodeToHighlight(activeCode); - }, [activeCode]); const [uiHidden, setUiHidden] = useState(false); const logBox = useRef(); // scroll log box to bottom when log changes @@ -191,6 +189,7 @@ function App() { uiHelpers.cleanup(); const parsed = await evaluate(_code); setPattern(parsed.pattern); + setActiveCode(_code); }} > 🎲 random @@ -201,7 +200,7 @@ function App() {
-
+
{/* onCursor={markParens} */} diff --git a/repl/src/CodeMirror6.jsx b/repl/src/CodeMirror6.jsx index 341ed0df..f82f5d62 100644 --- a/repl/src/CodeMirror6.jsx +++ b/repl/src/CodeMirror6.jsx @@ -18,26 +18,31 @@ const highlightField = StateField.define({ return Decoration.none; }, update(highlights, tr) { - highlights = highlights.map(tr.changes); - for (let e of tr.effects) { - if (e.is(addHighlight)) { - highlights = highlights.update({ - add: [highlightMark.range(e.value.from, e.value.to)], - }); - } - if (e.is(removeHighlight)) { - highlights = highlights.update({ - filter: (f, t, value) => { - if (f === e.value.from && t === e.value.to) { - return false; - } - return true; - // console.log('filter', f,t,value, e.value.from, e.value.to); - }, - }); + try { + highlights = highlights.map(tr.changes); + for (let e of tr.effects) { + if (e.is(addHighlight)) { + highlights = highlights.update({ + add: [highlightMark.range(e.value.from, e.value.to)], + }); + } + if (e.is(removeHighlight)) { + highlights = highlights.update({ + filter: (f, t, value) => { + if (f === e.value.from && t === e.value.to) { + return false; + } + return true; + // console.log('filter', f,t,value, e.value.from, e.value.to); + }, + }); + } } + return highlights; + } catch (err) { + // console.warn('highlighting error', err); + return highlights; } - return highlights; }, provide: (f) => EditorView.decorations.from(f), }); @@ -117,6 +122,10 @@ export function offsetToPosition(offset, code) { // returns absolute character offset from { line, ch } export function positionToOffset(position, code) { const lines = code.split('\n'); + if (position.line > lines.length) { + // throw new Error('positionToOffset: position.line > lines.length'); + return 0; + } let offset = 0; for (let i = 0; i < position.line; i++) { offset += lines[i].length + 1; diff --git a/repl/src/themes/material-palenight.js b/repl/src/themes/material-palenight.js index be7527c1..0f219155 100644 --- a/repl/src/themes/material-palenight.js +++ b/repl/src/themes/material-palenight.js @@ -26,6 +26,7 @@ export const materialPalenightTheme = EditorView.theme( '&': { color: '#ffffff', backgroundColor: background, + fontSize: '16px', 'z-index': 11, }, @@ -33,8 +34,8 @@ export const materialPalenightTheme = EditorView.theme( '.cm-content': { caretColor: cursor, }, - '.cm-line > *': { - background: '#00000070', + '.cm-line': { + background: '#2C323699', }, // done '&.cm-focused .cm-cursor': { @@ -68,7 +69,7 @@ export const materialPalenightTheme = EditorView.theme( // done '.cm-gutters': { - background, + background: '#2C323699', color: '#676e95', border: 'none', }, diff --git a/repl/src/useRepl.mjs b/repl/src/useRepl.mjs index c20a9cba..21605dce 100644 --- a/repl/src/useRepl.mjs +++ b/repl/src/useRepl.mjs @@ -11,7 +11,7 @@ let s4 = () => { }; const generateHash = (code) => encodeURIComponent(btoa(code)); -function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw }) { +function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw: onDrawProp }) { const id = useMemo(() => s4(), []); const [code, setCode] = useState(tune); const [activeCode, setActiveCode] = useState(); @@ -24,12 +24,12 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw }) { const pushLog = useCallback((message) => setLog((log) => log + `${log ? '\n\n' : ''}${message}`), []); // below block allows disabling the highlighting by including "strudel disable-highlighting" in the code (as comment) - onDraw = useMemo(() => { + const onDraw = useMemo(() => { if (activeCode && !activeCode.includes('strudel disable-highlighting')) { - return onDraw; + return (time, event) => onDrawProp(time, event, activeCode); } - }, [activeCode, onDraw]); - + }, [activeCode, onDrawProp]); + // cycle hook to control scheduling const cycle = useCycle({ onDraw, @@ -137,6 +137,7 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw }) { dirty, log, togglePlay, + setActiveCode, activateCode, activeCode, pushLog, From 37218e876484362b997e85264050293e4be35dec Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Mon, 25 Apr 2022 22:04:51 +0200 Subject: [PATCH 06/16] match font size of old editor --- repl/src/themes/material-palenight.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/repl/src/themes/material-palenight.js b/repl/src/themes/material-palenight.js index 0f219155..5ee559c9 100644 --- a/repl/src/themes/material-palenight.js +++ b/repl/src/themes/material-palenight.js @@ -26,13 +26,14 @@ export const materialPalenightTheme = EditorView.theme( '&': { color: '#ffffff', backgroundColor: background, - fontSize: '16px', + fontSize: '15px', 'z-index': 11, }, // done '.cm-content': { caretColor: cursor, + lineHeight: '22px', }, '.cm-line': { background: '#2C323699', From ef42ca692a0a166f5005cd3a551b3912d6edb571 Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 27 Apr 2022 20:57:08 -0400 Subject: [PATCH 07/16] Work on Codemirror 6 highlighting --- repl/src/App.js | 28 +++++++++++++++++-- repl/src/CodeMirror6.jsx | 60 ++++++++++------------------------------ 2 files changed, 41 insertions(+), 47 deletions(-) diff --git a/repl/src/App.js b/repl/src/App.js index ffd0a27a..2448ec62 100644 --- a/repl/src/App.js +++ b/repl/src/App.js @@ -1,5 +1,5 @@ import React, { useCallback, useLayoutEffect, useRef, useState, useEffect } from 'react'; -import CodeMirror6, { highlightEvent } from './CodeMirror6'; +import CodeMirror6, { setHighlights } from './CodeMirror6'; import cx from './cx'; import logo from './logo.svg'; import playStatic from './static.mjs'; @@ -91,7 +91,8 @@ function App() { tune: decoded || randomTune, defaultSynth, // onDraw: useCallback((time, event) => markEvent(editor)(time, event), [editor]), - onDraw: useCallback((_, e, code) => code && highlightEvent(e, view, code), [view]), + // onDraw: useCallback((_, e, code) => code && highlightEvent(e, view, code), [view]), + onDraw: () => {}, }); const [uiHidden, setUiHidden] = useState(false); const logBox = useRef(); @@ -118,6 +119,29 @@ function App() { return () => window.removeEventListener('keydown', handleKeyPress); }, [pattern, code, activateCode, cycle]); + useEffect(() => { + if (view) { + if (pattern && cycle.started) { + let frame = requestAnimationFrame(updateHighlights); + + function updateHighlights() { + let audioTime = Tone.Transport.seconds; + let timespan = new strudel.TimeSpan(audioTime, audioTime + 1 / 60); + let events = pattern.query(new strudel.State(timespan)); + view.dispatch({ effects: setHighlights.of(events) }); + + frame = requestAnimationFrame(updateHighlights); + } + + return () => { + cancelAnimationFrame(frame); + }; + } else { + view.dispatch({ effects: setHighlights.of([]) }); + } + } + }, [pattern, cycle.started]); + useWebMidi({ ready: useCallback( ({ outputs }) => { diff --git a/repl/src/CodeMirror6.jsx b/repl/src/CodeMirror6.jsx index f82f5d62..c182b702 100644 --- a/repl/src/CodeMirror6.jsx +++ b/repl/src/CodeMirror6.jsx @@ -7,8 +7,7 @@ import { javascript } from '@codemirror/lang-javascript'; import { materialPalenight } from './themes/material-palenight'; const highlightMark = Decoration.mark({ class: 'cm-highlight' }); -const addHighlight = StateEffect.define(); -const removeHighlight = StateEffect.define(); +export const setHighlights = StateEffect.define(); const highlightTheme = EditorView.baseTheme({ '.cm-highlight': { outline: '1px solid #FFCA28' }, // '.cm-highlight': { background: '#FFCA28' }, @@ -19,60 +18,29 @@ const highlightField = StateField.define({ }, update(highlights, tr) { try { - highlights = highlights.map(tr.changes); for (let e of tr.effects) { - if (e.is(addHighlight)) { - highlights = highlights.update({ - add: [highlightMark.range(e.value.from, e.value.to)], - }); - } - if (e.is(removeHighlight)) { - highlights = highlights.update({ - filter: (f, t, value) => { - if (f === e.value.from && t === e.value.to) { - return false; - } - return true; - // console.log('filter', f,t,value, e.value.from, e.value.to); - }, - }); + if (e.is(setHighlights)) { + highlights = Decoration.set( + e.value + .flatMap((event) => event.context.locations || []) + .map(({ start, end }) => { + let from = tr.newDoc.line(start.line).from + start.column; + let to = tr.newDoc.line(end.line).from + end.column; + return highlightMark.range(from, to); + }), + true, + ); } } return highlights; } catch (err) { - // console.warn('highlighting error', err); + console.warn('highlighting error', err); return highlights; } }, provide: (f) => EditorView.decorations.from(f), }); -// let timeouts = []; - -export const highlightEvent = (event, view, code) => { - if (!view) { - return; - } - const ranges = event.context?.locations?.map(({ start, end }) => { - return [start, end].map(({ line, column }) => positionToOffset({ line: line - 1, ch: column }, code)); - }); - const effects = ranges.map(([from, to]) => addHighlight.of({ from, to })); - - if (!effects.length) return false; - if (!view.state.field(highlightField, false)) { - effects.push(StateEffect.appendConfig.of([highlightField, highlightTheme])); - } - view.dispatch({ effects }); - // const index = timeouts.length; - // timeouts = timeouts.filter(time) - /* const timeout = */ setTimeout(() => { - const effects = ranges.map(([from, to]) => removeHighlight.of({ from, to })); - view.dispatch({ effects }); - // timeouts.splice(index, 1); - }, event.duration * 1000); - // timeouts.pusn({timeout,); -}; - export default function CodeMirror({ value, onChange, onViewChanged, onCursor, options, editorDidMount }) { return ( <> @@ -88,6 +56,8 @@ export default function CodeMirror({ value, onChange, onViewChanged, onCursor, o extensions={[ javascript(), materialPalenight, + highlightField, + highlightTheme, // theme, language, ... ]} /> From fc9a9e33d261dad7ad0c20d71f2592e8ea54253e Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 29 Apr 2022 16:27:23 +0200 Subject: [PATCH 08/16] use cm6 in tutorial + move highlighting to hook + optimize tutorial loading time --- repl/package-lock.json | 32 ++++++++++++++++++++++++++++++++ repl/package.json | 2 ++ repl/src/App.js | 34 +++------------------------------- repl/src/tutorial/MiniRepl.jsx | 32 +++++++++++++------------------- repl/src/useHighlighting.js | 28 ++++++++++++++++++++++++++++ repl/src/useRepl.mjs | 2 +- 6 files changed, 79 insertions(+), 51 deletions(-) create mode 100644 repl/src/useHighlighting.js diff --git a/repl/package-lock.json b/repl/package-lock.json index abe99f12..8574c551 100644 --- a/repl/package-lock.json +++ b/repl/package-lock.json @@ -20,6 +20,7 @@ "react-codemirror2": "^7.2.1", "react-codemirror6": "^1.1.0", "react-dom": "^17.0.2", + "react-hook-inview": "^4.4.1", "react-scripts": "5.0.0", "tone": "^14.7.77", "web-vitals": "^2.1.4" @@ -31,6 +32,7 @@ "autoprefixer": "^10.4.4", "parcel": "^2.3.1", "postcss": "^8.4.12", + "process": "^0.11.10", "serve": "^13.0.2", "tailwindcss": "^3.0.23" } @@ -16435,6 +16437,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -16861,6 +16872,15 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz", "integrity": "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA==" }, + "node_modules/react-hook-inview": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/react-hook-inview/-/react-hook-inview-4.4.1.tgz", + "integrity": "sha512-JKx0+aWCna0YUfTCKSaphGbaMp25S/YjpWtfk5VbqhlESesOEAPr7TCGMRLS3Cv6I1mEDhWYIhz2YLHgnHX4Yw==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -31994,6 +32014,12 @@ } } }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -32317,6 +32343,12 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz", "integrity": "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA==" }, + "react-hook-inview": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/react-hook-inview/-/react-hook-inview-4.4.1.tgz", + "integrity": "sha512-JKx0+aWCna0YUfTCKSaphGbaMp25S/YjpWtfk5VbqhlESesOEAPr7TCGMRLS3Cv6I1mEDhWYIhz2YLHgnHX4Yw==", + "requires": {} + }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", diff --git a/repl/package.json b/repl/package.json index f4e3a9a8..eccac897 100644 --- a/repl/package.json +++ b/repl/package.json @@ -16,6 +16,7 @@ "react-codemirror2": "^7.2.1", "react-codemirror6": "^1.1.0", "react-dom": "^17.0.2", + "react-hook-inview": "^4.4.1", "react-scripts": "5.0.0", "tone": "^14.7.77", "web-vitals": "^2.1.4" @@ -56,6 +57,7 @@ "autoprefixer": "^10.4.4", "parcel": "^2.3.1", "postcss": "^8.4.12", + "process": "^0.11.10", "serve": "^13.0.2", "tailwindcss": "^3.0.23" } diff --git a/repl/src/App.js b/repl/src/App.js index 2448ec62..46236294 100644 --- a/repl/src/App.js +++ b/repl/src/App.js @@ -33,6 +33,7 @@ import '@strudel.cycles/osc/osc.mjs'; import '@strudel.cycles/webaudio/webaudio.mjs'; import '@strudel.cycles/serial/serial.mjs'; import controls from '@strudel.cycles/core/controls.mjs'; +import useHighlighting from './useHighlighting'; extend( Tone, @@ -71,7 +72,6 @@ const defaultSynth = getDefaultSynth(); function App() { // const [editor, setEditor] = useState(); const [view, setView] = useState(); - const [codeToHighlight, setCodeToHighlight] = useState(); const { setCode, setPattern, @@ -90,11 +90,7 @@ function App() { } = useRepl({ tune: decoded || randomTune, defaultSynth, - // onDraw: useCallback((time, event) => markEvent(editor)(time, event), [editor]), - // onDraw: useCallback((_, e, code) => code && highlightEvent(e, view, code), [view]), - onDraw: () => {}, }); - const [uiHidden, setUiHidden] = useState(false); const logBox = useRef(); // scroll log box to bottom when log changes useLayoutEffect(() => { @@ -119,28 +115,7 @@ function App() { return () => window.removeEventListener('keydown', handleKeyPress); }, [pattern, code, activateCode, cycle]); - useEffect(() => { - if (view) { - if (pattern && cycle.started) { - let frame = requestAnimationFrame(updateHighlights); - - function updateHighlights() { - let audioTime = Tone.Transport.seconds; - let timespan = new strudel.TimeSpan(audioTime, audioTime + 1 / 60); - let events = pattern.query(new strudel.State(timespan)); - view.dispatch({ effects: setHighlights.of(events) }); - - frame = requestAnimationFrame(updateHighlights); - } - - return () => { - cancelAnimationFrame(frame); - }; - } else { - view.dispatch({ effects: setHighlights.of([]) }); - } - } - }, [pattern, cycle.started]); + useHighlighting({ view, pattern, started: cycle.started }); useWebMidi({ ready: useCallback( @@ -167,10 +142,7 @@ function App() {