fastled 1.4.19__tar.gz → 1.4.33__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastled-1.4.33/.vscode/launch.json +14 -0
- fastled-1.4.33/.vscode/tasks.json +55 -0
- {fastled-1.4.19 → fastled-1.4.33}/PKG-INFO +1 -1
- fastled-1.4.33/chrome_vscode_bridge_design_task.md +195 -0
- fastled-1.4.33/requirements.docker.txt +1 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/__version__.py +1 -1
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/app.py +10 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/args.py +15 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/client_server.py +57 -20
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/filewatcher.py +3 -0
- fastled-1.4.33/src/fastled/install/__init__.py +1 -0
- fastled-1.4.33/src/fastled/install/examples_manager.py +62 -0
- fastled-1.4.33/src/fastled/install/extension_manager.py +113 -0
- fastled-1.4.33/src/fastled/install/main.py +156 -0
- fastled-1.4.33/src/fastled/install/project_detection.py +167 -0
- fastled-1.4.33/src/fastled/install/test_install.py +373 -0
- fastled-1.4.33/src/fastled/install/vscode_config.py +167 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/open_browser.py +7 -4
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/parse_args.py +45 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/playwright/playwright_browser.py +123 -104
- fastled-1.4.33/src/fastled/playwright/resize_tracking.py +127 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/settings.py +1 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/types.py +4 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/web_compile.py +83 -9
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled.egg-info/PKG-INFO +1 -1
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled.egg-info/SOURCES.txt +11 -0
- fastled-1.4.33/task.md +292 -0
- fastled-1.4.33/task2.md +292 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/integration/test_libcompile.py +8 -2
- {fastled-1.4.19 → fastled-1.4.33}/tests/integration/test_playwright_integration.py +19 -18
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_manual_api_invocation.py +3 -3
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_session_compile.py +6 -6
- fastled-1.4.19/.vscode/launch.json +0 -44
- fastled-1.4.19/.vscode/tasks.json +0 -41
- fastled-1.4.19/requirements.docker.txt +0 -1
- {fastled-1.4.19 → fastled-1.4.33}/.aiderignore +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/.cursorrules +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/.dockerignore +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/build_multi_docker_image.yml +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/build_webpage.yml +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/lint.yml +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/publish_release.yml +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/template_build_docker_image.yml +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/test_build_exe.yml +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/test_macos.yml +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/test_ubuntu.yml +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/test_win.yml +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/.gitignore +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/.pylintrc +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/.vscode/settings.json +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/DEBUGGER.md +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/Dockerfile +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/FAQ.md +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/LICENSE +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/MANIFEST.in +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/README.md +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/RELEASE.md +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/TODO.md +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/build_exe.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/build_local_docker.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/build_site.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/clean +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/compiler/debug.sh +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/compiler/run.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/demo/100dots.html +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/demo/demo_threejs.html +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/demo/micdemo.html +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/demo/mp3upload.html +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/demo/webgl_postprocessing_unreal_bloom.html +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/docker-compose.yml +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/entrypoint.sh +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/install +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/install_linux.sh +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/lint +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/pyproject.toml +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/requirements.testing.txt +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/setup.cfg +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/setup.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/__init__.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/__main__.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/assets/example.txt +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/assets/localhost-key.pem +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/assets/localhost.pem +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/cli.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/cli_test.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/cli_test_interactive.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/compile_server.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/compile_server_impl.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/docker_manager.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/find_good_connection.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/interruptible_http.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/keyboard.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/keyz.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/live_client.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/paths.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/playwright/chrome_extension_downloader.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/print_filter.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/project_init.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/select_sketch_directory.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/server_flask.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/server_start.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/site/build.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/site/examples.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/sketch.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/spinner.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/string_diff.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/test/can_run_local_docker_tests.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/test/examples.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/util.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/version.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled/zip_files.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled.egg-info/dependency_links.txt +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled.egg-info/entry_points.txt +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled.egg-info/requires.txt +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/src/fastled.egg-info/top_level.txt +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/test +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/integration/test_build_examples.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/integration/test_examples.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/html/index.html +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_api.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_bad_ino.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_banner_string.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_cli.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_cli_no_platformio.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_compile_server.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_debug_fetch_source_files.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_docker_linux_on_windows.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_embedded_data.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_filechanger.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_flask_headers.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_http_server.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_ino/bad/bad.ino +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_ino/bad_platformio/bad_platformio.ino +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_ino/bad_platformio/platformio.ini +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_ino/embedded/data/bigdata.dat +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_ino/embedded/wasm.ino +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_ino/wasm/wasm.ino +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_no_platformio_compile.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_project_init.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_server_and_client_seperatly.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_string_diff.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_string_diff_comprehensive.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_version.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_webcompile.py +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/upload_package.sh +0 -0
- {fastled-1.4.19 → fastled-1.4.33}/vscode-plugin/readme +0 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
{
|
2
|
+
"version": "0.2.0",
|
3
|
+
"configurations": [
|
4
|
+
{
|
5
|
+
"name": "\ud83c\udfaf Auto Debug (Smart File Detection)",
|
6
|
+
"type": "auto-debug",
|
7
|
+
"request": "launch",
|
8
|
+
"map": {
|
9
|
+
"*.ino": "Arduino: Run .ino with FastLED",
|
10
|
+
"*.py": "Python: Current File (UV)"
|
11
|
+
}
|
12
|
+
}
|
13
|
+
]
|
14
|
+
}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
{
|
2
|
+
"version": "2.0.0",
|
3
|
+
"tasks": [
|
4
|
+
{
|
5
|
+
"type": "shell",
|
6
|
+
"label": "Run FastLED (Debug)",
|
7
|
+
"command": "fastled",
|
8
|
+
"args": [
|
9
|
+
"${file}",
|
10
|
+
"--debug",
|
11
|
+
"--app"
|
12
|
+
],
|
13
|
+
"options": {
|
14
|
+
"cwd": "${workspaceFolder}"
|
15
|
+
},
|
16
|
+
"group": {
|
17
|
+
"kind": "build",
|
18
|
+
"isDefault": true
|
19
|
+
},
|
20
|
+
"presentation": {
|
21
|
+
"echo": true,
|
22
|
+
"reveal": "always",
|
23
|
+
"focus": true,
|
24
|
+
"panel": "new",
|
25
|
+
"showReuseMessage": false,
|
26
|
+
"clear": true
|
27
|
+
},
|
28
|
+
"detail": "Run FastLED with debug mode and app visualization",
|
29
|
+
"problemMatcher": []
|
30
|
+
},
|
31
|
+
{
|
32
|
+
"type": "shell",
|
33
|
+
"label": "Run FastLED (Quick)",
|
34
|
+
"command": "fastled",
|
35
|
+
"args": [
|
36
|
+
"${file}",
|
37
|
+
"--background-update"
|
38
|
+
],
|
39
|
+
"options": {
|
40
|
+
"cwd": "${workspaceFolder}"
|
41
|
+
},
|
42
|
+
"group": "build",
|
43
|
+
"presentation": {
|
44
|
+
"echo": true,
|
45
|
+
"reveal": "always",
|
46
|
+
"focus": true,
|
47
|
+
"panel": "new",
|
48
|
+
"showReuseMessage": false,
|
49
|
+
"clear": true
|
50
|
+
},
|
51
|
+
"detail": "Run FastLED with quick background update mode",
|
52
|
+
"problemMatcher": []
|
53
|
+
}
|
54
|
+
]
|
55
|
+
}
|
@@ -0,0 +1,195 @@
|
|
1
|
+
Here’s a refined `chrome_vscode_bridge_design_task.md` file for your repo. Feel free to adjust paths, placeholders, or formatting to match your project's style.
|
2
|
+
|
3
|
+
---
|
4
|
+
|
5
|
+
# Chrome ↔ VSCode Bridge Design 🛠️
|
6
|
+
|
7
|
+
## Overview
|
8
|
+
|
9
|
+
Design and implement a minimal debugging bridge between a Python backend (using a hypothetical `fastled` library) and a Chrome-based frontend, invokable from VS Code. The goal is to allow:
|
10
|
+
|
11
|
+
* **Step-through debugging** (`step`, `next`, `in`, `out`)
|
12
|
+
* **Program counter**, call stack, local variable inspection
|
13
|
+
* Integration with VS Code Python or Node debugger
|
14
|
+
|
15
|
+
---
|
16
|
+
|
17
|
+
## 📘 Architecture
|
18
|
+
|
19
|
+
```
|
20
|
+
[VS Code] ↔ [Chrome Frontend CLI: Puppeteer + CDP] ↔ HTTP ↔ [Python Debug API (fastled)]
|
21
|
+
```
|
22
|
+
|
23
|
+
1. **Backend** (`Python + Flask`)
|
24
|
+
|
25
|
+
* Exposes endpoints:
|
26
|
+
|
27
|
+
* `POST /start` — begins execution, stops at first pause
|
28
|
+
* `POST /step/next` — advances one logical step
|
29
|
+
* `GET /state` — returns `{ pc, function, locals }`
|
30
|
+
* Internally uses generator-based control flow and `inspect` to snapshot state.
|
31
|
+
2. **Frontend** (`Node.js + Puppeteer`)
|
32
|
+
|
33
|
+
* Launches Chrome with remote-debugging enabled
|
34
|
+
* Serves a minimal UI (e.g. HTML + JS) to send `start`, `step`, and poll `state`
|
35
|
+
* Renders debugging state to the user; future CDP integration for real-time UI
|
36
|
+
3. **VS Code Integration**
|
37
|
+
|
38
|
+
* Launch configuration invokes the frontend script
|
39
|
+
* Stepping and inspection occur in the Chrome UI
|
40
|
+
* Optionally hooks into VS Code Debug Console for unified control
|
41
|
+
|
42
|
+
---
|
43
|
+
|
44
|
+
## 📄 Files
|
45
|
+
|
46
|
+
### 1. `debug_fastled_api.py` (Backend)
|
47
|
+
|
48
|
+
```python
|
49
|
+
import fastled, inspect
|
50
|
+
from flask import Flask, jsonify, request
|
51
|
+
|
52
|
+
app = Flask(__name__)
|
53
|
+
_state, _step_generator = {}, None
|
54
|
+
|
55
|
+
def compute(n):
|
56
|
+
x = n * 2
|
57
|
+
y = fastled.compute(x)
|
58
|
+
yield from report_and_pause()
|
59
|
+
return y
|
60
|
+
|
61
|
+
def report_and_pause():
|
62
|
+
frame = inspect.currentframe().f_back
|
63
|
+
_state.update({
|
64
|
+
"pc": frame.f_lineno,
|
65
|
+
"func": frame.f_code.co_name,
|
66
|
+
"locals": frame.f_locals.copy()
|
67
|
+
})
|
68
|
+
yield True
|
69
|
+
|
70
|
+
@app.route('/start', methods=['POST'])
|
71
|
+
def start():
|
72
|
+
global _step_generator
|
73
|
+
n = request.json.get("n", 5)
|
74
|
+
def runner():
|
75
|
+
gen = compute(n)
|
76
|
+
try: next(gen)
|
77
|
+
except StopIteration: pass
|
78
|
+
_step_generator = runner
|
79
|
+
return jsonify({"status": "started"})
|
80
|
+
|
81
|
+
@app.route('/state', methods=['GET'])
|
82
|
+
def state():
|
83
|
+
return jsonify(_state)
|
84
|
+
|
85
|
+
@app.route('/step/next', methods=['POST'])
|
86
|
+
def step_next():
|
87
|
+
try:
|
88
|
+
_step_generator()
|
89
|
+
return jsonify({"status": "paused", **_state})
|
90
|
+
except Exception:
|
91
|
+
return jsonify({"status": "done"})
|
92
|
+
|
93
|
+
if __name__ == "__main__":
|
94
|
+
app.run(port=5000)
|
95
|
+
```
|
96
|
+
|
97
|
+
---
|
98
|
+
|
99
|
+
### 2. `debug_fastled_frontend.js` (Frontend)
|
100
|
+
|
101
|
+
```js
|
102
|
+
const puppeteer = require('puppeteer-core');
|
103
|
+
const fetch = require('node-fetch');
|
104
|
+
|
105
|
+
(async () => {
|
106
|
+
const browser = await puppeteer.launch({
|
107
|
+
executablePath: '/path/to/chrome',
|
108
|
+
args: ['--remote-debugging-port=9222']
|
109
|
+
});
|
110
|
+
const [page] = await browser.pages();
|
111
|
+
|
112
|
+
const html = `
|
113
|
+
<button id="start">Start</button>
|
114
|
+
<button id="step">Next</button>
|
115
|
+
<pre id="out"></pre>
|
116
|
+
<script>
|
117
|
+
document.getElementById('start').onclick = async () => {
|
118
|
+
await fetch('http://localhost:5000/start', {
|
119
|
+
method: 'POST',
|
120
|
+
headers: { 'Content-Type': 'application/json' },
|
121
|
+
body: JSON.stringify({ n: 10 })
|
122
|
+
});
|
123
|
+
update();
|
124
|
+
};
|
125
|
+
document.getElementById('step').onclick = async () => {
|
126
|
+
await fetch('http://localhost:5000/step/next', { method: 'POST' });
|
127
|
+
update();
|
128
|
+
};
|
129
|
+
async function update() {
|
130
|
+
const res = await fetch('http://localhost:5000/state');
|
131
|
+
document.getElementById('out').textContent = JSON.stringify(await res.json(), null, 2);
|
132
|
+
}
|
133
|
+
</script>
|
134
|
+
`;
|
135
|
+
await page.setContent(html);
|
136
|
+
})();
|
137
|
+
```
|
138
|
+
|
139
|
+
---
|
140
|
+
|
141
|
+
## ⛓️ Integration with VS Code
|
142
|
+
|
143
|
+
Add this to `.vscode/launch.json`:
|
144
|
+
|
145
|
+
```jsonc
|
146
|
+
{
|
147
|
+
"configurations": [
|
148
|
+
{
|
149
|
+
"name": "Chrome-FastLED Debug Bridge",
|
150
|
+
"type": "node",
|
151
|
+
"request": "launch",
|
152
|
+
"program": "${workspaceFolder}/debug_fastled_frontend.js"
|
153
|
+
}
|
154
|
+
]
|
155
|
+
}
|
156
|
+
```
|
157
|
+
|
158
|
+
* Launch this first to start Chrome with debugging enabled
|
159
|
+
* Use the UI to `Start`, `Next`, and inspect state output
|
160
|
+
* Optionally, add CDP logic to highlight lines in VS Code or Chrome DevTools
|
161
|
+
|
162
|
+
---
|
163
|
+
|
164
|
+
## ✅ Roadmap & Next Steps
|
165
|
+
|
166
|
+
| Task | Status |
|
167
|
+
| --------------------------------------- | ------------- |
|
168
|
+
| Generator-based stepping API | ✅ Implemented |
|
169
|
+
| Backend state introspection (PC/locals) | ✅ Implemented |
|
170
|
+
| Frontend stepping UI (buttons + state) | ✅ Implemented |
|
171
|
+
| VS Code `launch.json` integration | ✅ Drafted |
|
172
|
+
| CDP / DevTools integration | 🔲 To Do |
|
173
|
+
| Support for `step in`, `step out` | 🔲 To Do |
|
174
|
+
| Breakpoints, multi-file support | 🔲 To Do |
|
175
|
+
|
176
|
+
---
|
177
|
+
|
178
|
+
## 🔧 Future Enhancements
|
179
|
+
|
180
|
+
* **Full CDP client**: translate HTTP state to actual Chrome DevTools UI breakpoints/stepping
|
181
|
+
* **Rich UI**: live code view, synchronized highlighting, variable inspectors
|
182
|
+
* **Language-agnostic bridge**: plug in Node.js or other backends
|
183
|
+
* **VS Code Extension support**: unify stepping flows and tooltips
|
184
|
+
|
185
|
+
---
|
186
|
+
|
187
|
+
## 📎 Summary
|
188
|
+
|
189
|
+
This bridge provides:
|
190
|
+
|
191
|
+
* A **Python backend** exposing stepping and state via HTTP
|
192
|
+
* A **Node.js/pupeteer frontend** for remote-debug Chrome UI
|
193
|
+
* **VS Code launch config** for seamless integration
|
194
|
+
|
195
|
+
You're all set to explore, refine, or build upon this foundation. Let me know if you'd like help developing CDP integration or full VS Code extension support!
|
@@ -0,0 +1 @@
|
|
1
|
+
fastled-wasm-server>=1.1.37
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# IMPORTANT! There's a bug in github which will REJECT any version update
|
2
2
|
# that has any other change in the repo. Please bump the version as the
|
3
3
|
# ONLY change in a commit, or else the pypi update and the release will fail.
|
4
|
-
__version__ = "1.4.
|
4
|
+
__version__ = "1.4.33"
|
5
5
|
|
6
6
|
__version_url_latest__ = "https://raw.githubusercontent.com/zackees/fastled-wasm/refs/heads/main/src/fastled/__version__.py"
|
@@ -51,6 +51,16 @@ def main() -> int:
|
|
51
51
|
from fastled.select_sketch_directory import select_sketch_directory
|
52
52
|
|
53
53
|
args = parse_args()
|
54
|
+
|
55
|
+
# Handle --install command early
|
56
|
+
if args.install:
|
57
|
+
from fastled.install.main import fastled_install
|
58
|
+
|
59
|
+
result = fastled_install(
|
60
|
+
dry_run=args.dry_run, no_interactive=args.no_interactive
|
61
|
+
)
|
62
|
+
return 0 if result else 1
|
63
|
+
|
54
64
|
interactive: bool = args.interactive
|
55
65
|
has_server = args.server
|
56
66
|
update: bool = args.update
|
@@ -26,6 +26,9 @@ class Args:
|
|
26
26
|
release: bool
|
27
27
|
ram_disk_size: str # suffixed liked "25mb" or "1gb"
|
28
28
|
clear = False # Force the last running container to be removed. Useful for benchmarking.
|
29
|
+
install: bool = False # Install FastLED development environment
|
30
|
+
dry_run: bool = False # Dry run mode for testing
|
31
|
+
no_interactive: bool = False # Non-interactive mode
|
29
32
|
|
30
33
|
@staticmethod
|
31
34
|
def from_namespace(args: argparse.Namespace) -> "Args":
|
@@ -72,6 +75,15 @@ class Args:
|
|
72
75
|
assert isinstance(
|
73
76
|
args.release, bool
|
74
77
|
), f"expected bool, got {type(args.release)}"
|
78
|
+
assert isinstance(
|
79
|
+
args.install, bool
|
80
|
+
), f"expected bool, got {type(args.install)}"
|
81
|
+
assert isinstance(
|
82
|
+
args.dry_run, bool
|
83
|
+
), f"expected bool, got {type(args.dry_run)}"
|
84
|
+
assert isinstance(
|
85
|
+
args.no_interactive, bool
|
86
|
+
), f"expected bool, got {type(args.no_interactive)}"
|
75
87
|
|
76
88
|
init: bool | str = False
|
77
89
|
if args.init is None:
|
@@ -101,4 +113,7 @@ class Args:
|
|
101
113
|
quick=args.quick,
|
102
114
|
release=args.release,
|
103
115
|
ram_disk_size=args.ram_disk_size,
|
116
|
+
install=args.install,
|
117
|
+
dry_run=args.dry_run,
|
118
|
+
no_interactive=args.no_interactive,
|
104
119
|
)
|
@@ -100,7 +100,7 @@ def _run_web_compiler(
|
|
100
100
|
|
101
101
|
# Guard: libfastled compilation requires volume source mapping
|
102
102
|
if not allow_libcompile:
|
103
|
-
print("⚠️ libfastled compilation disabled
|
103
|
+
print("⚠️ libfastled compilation disabled.")
|
104
104
|
|
105
105
|
start = time.time()
|
106
106
|
web_result = web_compile(
|
@@ -122,14 +122,59 @@ def _run_web_compiler(
|
|
122
122
|
(output_dir / "index.html").write_text(error_html, encoding="utf-8")
|
123
123
|
return web_result
|
124
124
|
|
125
|
+
# Extract zip contents to fastled_js directory
|
126
|
+
extraction_start_time = time.time()
|
127
|
+
output_dir.mkdir(exist_ok=True)
|
128
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
129
|
+
temp_path = Path(temp_dir)
|
130
|
+
temp_zip = temp_path / "result.zip"
|
131
|
+
temp_zip.write_bytes(web_result.zip_bytes)
|
132
|
+
|
133
|
+
# Clear existing contents
|
134
|
+
shutil.rmtree(output_dir, ignore_errors=True)
|
135
|
+
output_dir.mkdir(exist_ok=True)
|
136
|
+
|
137
|
+
# Extract zip contents
|
138
|
+
shutil.unpack_archive(temp_zip, output_dir, "zip")
|
139
|
+
extraction_time = time.time() - extraction_start_time
|
140
|
+
|
125
141
|
def print_results() -> None:
|
126
142
|
hash_value = (
|
127
143
|
web_result.hash_value
|
128
144
|
if web_result.hash_value is not None
|
129
145
|
else "NO HASH VALUE"
|
130
146
|
)
|
147
|
+
|
148
|
+
# Build timing breakdown
|
149
|
+
timing_breakdown = f" Time: {diff:.2f} (seconds)"
|
150
|
+
if hasattr(web_result, "zip_time"):
|
151
|
+
timing_breakdown += f"\n zip creation: {web_result.zip_time:.2f}"
|
152
|
+
if web_result.libfastled_time > 0:
|
153
|
+
timing_breakdown += (
|
154
|
+
f"\n libfastled: {web_result.libfastled_time:.2f}"
|
155
|
+
)
|
156
|
+
timing_breakdown += (
|
157
|
+
f"\n sketch compile + link: {web_result.sketch_time:.2f}"
|
158
|
+
)
|
159
|
+
if hasattr(web_result, "response_processing_time"):
|
160
|
+
timing_breakdown += f"\n response processing: {web_result.response_processing_time:.2f}"
|
161
|
+
|
162
|
+
# Calculate any unaccounted time
|
163
|
+
accounted_time = (
|
164
|
+
web_result.zip_time
|
165
|
+
+ web_result.libfastled_time
|
166
|
+
+ web_result.sketch_time
|
167
|
+
+ web_result.response_processing_time
|
168
|
+
+ extraction_time
|
169
|
+
)
|
170
|
+
unaccounted_time = diff - accounted_time
|
171
|
+
if extraction_time > 0.01:
|
172
|
+
timing_breakdown += f"\n extraction: {extraction_time:.2f}"
|
173
|
+
if unaccounted_time > 0.01:
|
174
|
+
timing_breakdown += f"\n other overhead: {unaccounted_time:.2f}"
|
175
|
+
|
131
176
|
print(
|
132
|
-
f"\nWeb compilation successful\n
|
177
|
+
f"\nWeb compilation successful\n{timing_breakdown}\n output: {output_dir}\n hash: {hash_value}\n zip size: {len(web_result.zip_bytes)} bytes"
|
133
178
|
)
|
134
179
|
|
135
180
|
# now check to see if the hash value is the same as the last hash value
|
@@ -138,20 +183,6 @@ def _run_web_compiler(
|
|
138
183
|
print_results()
|
139
184
|
return web_result
|
140
185
|
|
141
|
-
# Extract zip contents to fastled_js directory
|
142
|
-
output_dir.mkdir(exist_ok=True)
|
143
|
-
with tempfile.TemporaryDirectory() as temp_dir:
|
144
|
-
temp_path = Path(temp_dir)
|
145
|
-
temp_zip = temp_path / "result.zip"
|
146
|
-
temp_zip.write_bytes(web_result.zip_bytes)
|
147
|
-
|
148
|
-
# Clear existing contents
|
149
|
-
shutil.rmtree(output_dir, ignore_errors=True)
|
150
|
-
output_dir.mkdir(exist_ok=True)
|
151
|
-
|
152
|
-
# Extract zip contents
|
153
|
-
shutil.unpack_archive(temp_zip, output_dir, "zip")
|
154
|
-
|
155
186
|
_chunked_print(web_result.stdout)
|
156
187
|
print_results()
|
157
188
|
return web_result
|
@@ -255,6 +286,11 @@ def _background_update_docker_image() -> None:
|
|
255
286
|
print("✅ Background docker image update completed successfully.")
|
256
287
|
else:
|
257
288
|
print("ℹ️ Docker image was already up to date.")
|
289
|
+
except KeyboardInterrupt:
|
290
|
+
print("⚠️ Background docker image update interrupted by user.")
|
291
|
+
import _thread
|
292
|
+
|
293
|
+
_thread.interrupt_main()
|
258
294
|
except Exception as e:
|
259
295
|
print(f"⚠️ Background docker image update failed: {e}")
|
260
296
|
|
@@ -489,9 +525,6 @@ def run_client(
|
|
489
525
|
print(f"\nChanges detected in FastLED source code: {changed_files}")
|
490
526
|
print("Press space bar to trigger compile.")
|
491
527
|
|
492
|
-
# Re-evaluate libcompile capability when source code changes
|
493
|
-
allow_libcompile = True
|
494
|
-
|
495
528
|
while True:
|
496
529
|
space_bar_pressed = SpaceBarWatcher.watch_space_bar_pressed(
|
497
530
|
timeout=1.0
|
@@ -505,6 +538,8 @@ def run_client(
|
|
505
538
|
print(
|
506
539
|
f"Changes detected in {file_changes}\nHit the space bar to trigger compile."
|
507
540
|
)
|
541
|
+
# Re-evaluate libcompile capability when source code changes
|
542
|
+
allow_libcompile = True
|
508
543
|
|
509
544
|
if space_bar_pressed or sketch_files_changed:
|
510
545
|
if space_bar_pressed:
|
@@ -516,7 +551,9 @@ def run_client(
|
|
516
551
|
last_compiled_result = compile_function(
|
517
552
|
last_hash_value=None, allow_libcompile=allow_libcompile
|
518
553
|
)
|
519
|
-
allow_libcompile =
|
554
|
+
allow_libcompile = (
|
555
|
+
allow_libcompile and not last_compiled_result.success
|
556
|
+
)
|
520
557
|
print("Finished recompile.")
|
521
558
|
# Drain the space bar queue
|
522
559
|
SpaceBarWatcher.watch_space_bar_pressed()
|
@@ -0,0 +1 @@
|
|
1
|
+
"""FastLED install module."""
|
@@ -0,0 +1,62 @@
|
|
1
|
+
"""Examples installation manager using FastLED's built-in --project-init command."""
|
2
|
+
|
3
|
+
import subprocess
|
4
|
+
|
5
|
+
|
6
|
+
def install_fastled_examples_via_project_init(
|
7
|
+
force: bool = False, no_interactive: bool = False
|
8
|
+
) -> bool:
|
9
|
+
"""
|
10
|
+
Install FastLED examples using built-in --project-init command.
|
11
|
+
|
12
|
+
Args:
|
13
|
+
force: If True, install without prompting
|
14
|
+
no_interactive: If True, skip prompting and return False
|
15
|
+
|
16
|
+
Returns:
|
17
|
+
True if installation successful, False otherwise
|
18
|
+
"""
|
19
|
+
if not force:
|
20
|
+
if no_interactive:
|
21
|
+
print("⚠️ No existing Arduino content found.")
|
22
|
+
print(" In non-interactive mode, skipping examples installation.")
|
23
|
+
print(" Run 'fastled --project-init' manually to install examples.")
|
24
|
+
return False
|
25
|
+
|
26
|
+
print("No existing Arduino content found.")
|
27
|
+
answer = (
|
28
|
+
input("Would you like to install FastLED examples? [y/n] ").strip().lower()
|
29
|
+
)
|
30
|
+
if answer not in ["y", "yes"]:
|
31
|
+
print("Skipping FastLED examples installation.")
|
32
|
+
return False
|
33
|
+
|
34
|
+
print("📦 Installing FastLED examples using project initialization...")
|
35
|
+
|
36
|
+
try:
|
37
|
+
# Use FastLED's built-in project initialization
|
38
|
+
subprocess.run(
|
39
|
+
["fastled", "--project-init"],
|
40
|
+
check=True,
|
41
|
+
capture_output=True,
|
42
|
+
text=True,
|
43
|
+
cwd=".",
|
44
|
+
)
|
45
|
+
|
46
|
+
print("✅ FastLED project initialized successfully!")
|
47
|
+
print("📁 Examples and project structure created")
|
48
|
+
print("🚀 Quick start: Check for generated .ino files and press F5 to debug")
|
49
|
+
|
50
|
+
return True
|
51
|
+
|
52
|
+
except subprocess.CalledProcessError as e:
|
53
|
+
print(f"⚠️ Warning: Failed to initialize FastLED project: {e}")
|
54
|
+
if e.stderr:
|
55
|
+
print(f"Error details: {e.stderr}")
|
56
|
+
print("You can manually run: fastled --project-init")
|
57
|
+
return False
|
58
|
+
except FileNotFoundError:
|
59
|
+
print("⚠️ Warning: FastLED package not found. Please install it first:")
|
60
|
+
print(" pip install fastled")
|
61
|
+
print("Then run: fastled --project-init")
|
62
|
+
return False
|
@@ -0,0 +1,113 @@
|
|
1
|
+
"""Auto Debug extension installation manager."""
|
2
|
+
|
3
|
+
import shutil
|
4
|
+
import subprocess
|
5
|
+
import tempfile
|
6
|
+
from pathlib import Path
|
7
|
+
from urllib.request import urlretrieve
|
8
|
+
|
9
|
+
|
10
|
+
def download_auto_debug_extension() -> Path | None:
|
11
|
+
"""
|
12
|
+
Download the Auto Debug extension .vsix file from GitHub.
|
13
|
+
|
14
|
+
Returns:
|
15
|
+
Path to downloaded .vsix file, or None if download fails
|
16
|
+
"""
|
17
|
+
# URL for the Auto Debug extension
|
18
|
+
extension_url = "https://github.com/zackees/vscode-auto-debug/releases/latest/download/auto-debug.vsix"
|
19
|
+
|
20
|
+
try:
|
21
|
+
# Create temporary directory
|
22
|
+
temp_dir = Path(tempfile.mkdtemp())
|
23
|
+
vsix_path = temp_dir / "auto-debug.vsix"
|
24
|
+
|
25
|
+
print("📥 Downloading Auto Debug extension...")
|
26
|
+
|
27
|
+
# Download the file
|
28
|
+
urlretrieve(extension_url, vsix_path)
|
29
|
+
|
30
|
+
if vsix_path.exists() and vsix_path.stat().st_size > 0:
|
31
|
+
print("✅ Extension downloaded successfully")
|
32
|
+
return vsix_path
|
33
|
+
else:
|
34
|
+
print("❌ Failed to download extension")
|
35
|
+
return None
|
36
|
+
|
37
|
+
except Exception as e:
|
38
|
+
print(f"❌ Error downloading extension: {e}")
|
39
|
+
return None
|
40
|
+
|
41
|
+
|
42
|
+
def install_vscode_extensions(extension_path: Path) -> bool:
|
43
|
+
"""
|
44
|
+
Install extension in VSCode or Cursor.
|
45
|
+
|
46
|
+
Args:
|
47
|
+
extension_path: Path to .vsix file
|
48
|
+
|
49
|
+
Returns:
|
50
|
+
True if installation successful, False otherwise
|
51
|
+
"""
|
52
|
+
# Try VSCode first
|
53
|
+
if shutil.which("code"):
|
54
|
+
ide_command = "code"
|
55
|
+
ide_name = "VSCode"
|
56
|
+
elif shutil.which("cursor"):
|
57
|
+
ide_command = "cursor"
|
58
|
+
ide_name = "Cursor"
|
59
|
+
else:
|
60
|
+
print("❌ No supported IDE found (VSCode or Cursor)")
|
61
|
+
return False
|
62
|
+
|
63
|
+
try:
|
64
|
+
print(f"📦 Installing extension in {ide_name}...")
|
65
|
+
|
66
|
+
# Install the extension
|
67
|
+
subprocess.run(
|
68
|
+
[ide_command, "--install-extension", str(extension_path)],
|
69
|
+
capture_output=True,
|
70
|
+
text=True,
|
71
|
+
check=True,
|
72
|
+
)
|
73
|
+
|
74
|
+
print(f"✅ Auto Debug extension installed in {ide_name}")
|
75
|
+
return True
|
76
|
+
|
77
|
+
except subprocess.CalledProcessError as e:
|
78
|
+
print(f"❌ Failed to install extension: {e}")
|
79
|
+
if e.stderr:
|
80
|
+
print(f"Error details: {e.stderr}")
|
81
|
+
return False
|
82
|
+
finally:
|
83
|
+
# Clean up temporary file
|
84
|
+
if extension_path.exists():
|
85
|
+
try:
|
86
|
+
extension_path.unlink()
|
87
|
+
extension_path.parent.rmdir()
|
88
|
+
except Exception:
|
89
|
+
pass
|
90
|
+
|
91
|
+
|
92
|
+
def install_auto_debug_extension(dry_run: bool = False) -> bool:
|
93
|
+
"""
|
94
|
+
Main function to download and install Auto Debug extension.
|
95
|
+
|
96
|
+
Args:
|
97
|
+
dry_run: If True, simulate installation without actually installing
|
98
|
+
|
99
|
+
Returns:
|
100
|
+
True if installation successful, False otherwise
|
101
|
+
"""
|
102
|
+
if dry_run:
|
103
|
+
print("[DRY-RUN]: Would download and install Auto Debug extension")
|
104
|
+
print("[DRY-RUN]: NO PLUGIN INSTALLED")
|
105
|
+
return True
|
106
|
+
|
107
|
+
# Download extension
|
108
|
+
vsix_path = download_auto_debug_extension()
|
109
|
+
if not vsix_path:
|
110
|
+
return False
|
111
|
+
|
112
|
+
# Install extension
|
113
|
+
return install_vscode_extensions(vsix_path)
|