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.
Files changed (146) hide show
  1. fastled-1.4.33/.vscode/launch.json +14 -0
  2. fastled-1.4.33/.vscode/tasks.json +55 -0
  3. {fastled-1.4.19 → fastled-1.4.33}/PKG-INFO +1 -1
  4. fastled-1.4.33/chrome_vscode_bridge_design_task.md +195 -0
  5. fastled-1.4.33/requirements.docker.txt +1 -0
  6. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/__version__.py +1 -1
  7. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/app.py +10 -0
  8. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/args.py +15 -0
  9. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/client_server.py +57 -20
  10. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/filewatcher.py +3 -0
  11. fastled-1.4.33/src/fastled/install/__init__.py +1 -0
  12. fastled-1.4.33/src/fastled/install/examples_manager.py +62 -0
  13. fastled-1.4.33/src/fastled/install/extension_manager.py +113 -0
  14. fastled-1.4.33/src/fastled/install/main.py +156 -0
  15. fastled-1.4.33/src/fastled/install/project_detection.py +167 -0
  16. fastled-1.4.33/src/fastled/install/test_install.py +373 -0
  17. fastled-1.4.33/src/fastled/install/vscode_config.py +167 -0
  18. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/open_browser.py +7 -4
  19. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/parse_args.py +45 -0
  20. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/playwright/playwright_browser.py +123 -104
  21. fastled-1.4.33/src/fastled/playwright/resize_tracking.py +127 -0
  22. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/settings.py +1 -0
  23. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/types.py +4 -0
  24. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/web_compile.py +83 -9
  25. {fastled-1.4.19 → fastled-1.4.33}/src/fastled.egg-info/PKG-INFO +1 -1
  26. {fastled-1.4.19 → fastled-1.4.33}/src/fastled.egg-info/SOURCES.txt +11 -0
  27. fastled-1.4.33/task.md +292 -0
  28. fastled-1.4.33/task2.md +292 -0
  29. {fastled-1.4.19 → fastled-1.4.33}/tests/integration/test_libcompile.py +8 -2
  30. {fastled-1.4.19 → fastled-1.4.33}/tests/integration/test_playwright_integration.py +19 -18
  31. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_manual_api_invocation.py +3 -3
  32. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_session_compile.py +6 -6
  33. fastled-1.4.19/.vscode/launch.json +0 -44
  34. fastled-1.4.19/.vscode/tasks.json +0 -41
  35. fastled-1.4.19/requirements.docker.txt +0 -1
  36. {fastled-1.4.19 → fastled-1.4.33}/.aiderignore +0 -0
  37. {fastled-1.4.19 → fastled-1.4.33}/.cursorrules +0 -0
  38. {fastled-1.4.19 → fastled-1.4.33}/.dockerignore +0 -0
  39. {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/build_multi_docker_image.yml +0 -0
  40. {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/build_webpage.yml +0 -0
  41. {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/lint.yml +0 -0
  42. {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/publish_release.yml +0 -0
  43. {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/template_build_docker_image.yml +0 -0
  44. {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/test_build_exe.yml +0 -0
  45. {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/test_macos.yml +0 -0
  46. {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/test_ubuntu.yml +0 -0
  47. {fastled-1.4.19 → fastled-1.4.33}/.github/workflows/test_win.yml +0 -0
  48. {fastled-1.4.19 → fastled-1.4.33}/.gitignore +0 -0
  49. {fastled-1.4.19 → fastled-1.4.33}/.pylintrc +0 -0
  50. {fastled-1.4.19 → fastled-1.4.33}/.vscode/settings.json +0 -0
  51. {fastled-1.4.19 → fastled-1.4.33}/DEBUGGER.md +0 -0
  52. {fastled-1.4.19 → fastled-1.4.33}/Dockerfile +0 -0
  53. {fastled-1.4.19 → fastled-1.4.33}/FAQ.md +0 -0
  54. {fastled-1.4.19 → fastled-1.4.33}/LICENSE +0 -0
  55. {fastled-1.4.19 → fastled-1.4.33}/MANIFEST.in +0 -0
  56. {fastled-1.4.19 → fastled-1.4.33}/README.md +0 -0
  57. {fastled-1.4.19 → fastled-1.4.33}/RELEASE.md +0 -0
  58. {fastled-1.4.19 → fastled-1.4.33}/TODO.md +0 -0
  59. {fastled-1.4.19 → fastled-1.4.33}/build_exe.py +0 -0
  60. {fastled-1.4.19 → fastled-1.4.33}/build_local_docker.py +0 -0
  61. {fastled-1.4.19 → fastled-1.4.33}/build_site.py +0 -0
  62. {fastled-1.4.19 → fastled-1.4.33}/clean +0 -0
  63. {fastled-1.4.19 → fastled-1.4.33}/compiler/debug.sh +0 -0
  64. {fastled-1.4.19 → fastled-1.4.33}/compiler/run.py +0 -0
  65. {fastled-1.4.19 → fastled-1.4.33}/demo/100dots.html +0 -0
  66. {fastled-1.4.19 → fastled-1.4.33}/demo/demo_threejs.html +0 -0
  67. {fastled-1.4.19 → fastled-1.4.33}/demo/micdemo.html +0 -0
  68. {fastled-1.4.19 → fastled-1.4.33}/demo/mp3upload.html +0 -0
  69. {fastled-1.4.19 → fastled-1.4.33}/demo/webgl_postprocessing_unreal_bloom.html +0 -0
  70. {fastled-1.4.19 → fastled-1.4.33}/docker-compose.yml +0 -0
  71. {fastled-1.4.19 → fastled-1.4.33}/entrypoint.sh +0 -0
  72. {fastled-1.4.19 → fastled-1.4.33}/install +0 -0
  73. {fastled-1.4.19 → fastled-1.4.33}/install_linux.sh +0 -0
  74. {fastled-1.4.19 → fastled-1.4.33}/lint +0 -0
  75. {fastled-1.4.19 → fastled-1.4.33}/pyproject.toml +0 -0
  76. {fastled-1.4.19 → fastled-1.4.33}/requirements.testing.txt +0 -0
  77. {fastled-1.4.19 → fastled-1.4.33}/setup.cfg +0 -0
  78. {fastled-1.4.19 → fastled-1.4.33}/setup.py +0 -0
  79. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/__init__.py +0 -0
  80. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/__main__.py +0 -0
  81. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/assets/example.txt +0 -0
  82. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/assets/localhost-key.pem +0 -0
  83. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/assets/localhost.pem +0 -0
  84. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/cli.py +0 -0
  85. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/cli_test.py +0 -0
  86. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/cli_test_interactive.py +0 -0
  87. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/compile_server.py +0 -0
  88. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/compile_server_impl.py +0 -0
  89. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/docker_manager.py +0 -0
  90. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/find_good_connection.py +0 -0
  91. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/interruptible_http.py +0 -0
  92. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/keyboard.py +0 -0
  93. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/keyz.py +0 -0
  94. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/live_client.py +0 -0
  95. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/paths.py +0 -0
  96. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/playwright/chrome_extension_downloader.py +0 -0
  97. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/print_filter.py +0 -0
  98. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/project_init.py +0 -0
  99. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/select_sketch_directory.py +0 -0
  100. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/server_flask.py +0 -0
  101. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/server_start.py +0 -0
  102. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/site/build.py +0 -0
  103. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/site/examples.py +0 -0
  104. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/sketch.py +0 -0
  105. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/spinner.py +0 -0
  106. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/string_diff.py +0 -0
  107. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/test/can_run_local_docker_tests.py +0 -0
  108. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/test/examples.py +0 -0
  109. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/util.py +0 -0
  110. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/version.py +0 -0
  111. {fastled-1.4.19 → fastled-1.4.33}/src/fastled/zip_files.py +0 -0
  112. {fastled-1.4.19 → fastled-1.4.33}/src/fastled.egg-info/dependency_links.txt +0 -0
  113. {fastled-1.4.19 → fastled-1.4.33}/src/fastled.egg-info/entry_points.txt +0 -0
  114. {fastled-1.4.19 → fastled-1.4.33}/src/fastled.egg-info/requires.txt +0 -0
  115. {fastled-1.4.19 → fastled-1.4.33}/src/fastled.egg-info/top_level.txt +0 -0
  116. {fastled-1.4.19 → fastled-1.4.33}/test +0 -0
  117. {fastled-1.4.19 → fastled-1.4.33}/tests/integration/test_build_examples.py +0 -0
  118. {fastled-1.4.19 → fastled-1.4.33}/tests/integration/test_examples.py +0 -0
  119. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/html/index.html +0 -0
  120. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_api.py +0 -0
  121. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_bad_ino.py +0 -0
  122. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_banner_string.py +0 -0
  123. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_cli.py +0 -0
  124. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_cli_no_platformio.py +0 -0
  125. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_compile_server.py +0 -0
  126. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_debug_fetch_source_files.py +0 -0
  127. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_docker_linux_on_windows.py +0 -0
  128. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_embedded_data.py +0 -0
  129. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_filechanger.py +0 -0
  130. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_flask_headers.py +0 -0
  131. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_http_server.py +0 -0
  132. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_ino/bad/bad.ino +0 -0
  133. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_ino/bad_platformio/bad_platformio.ino +0 -0
  134. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_ino/bad_platformio/platformio.ini +0 -0
  135. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_ino/embedded/data/bigdata.dat +0 -0
  136. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_ino/embedded/wasm.ino +0 -0
  137. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_ino/wasm/wasm.ino +0 -0
  138. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_no_platformio_compile.py +0 -0
  139. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_project_init.py +0 -0
  140. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_server_and_client_seperatly.py +0 -0
  141. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_string_diff.py +0 -0
  142. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_string_diff_comprehensive.py +0 -0
  143. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_version.py +0 -0
  144. {fastled-1.4.19 → fastled-1.4.33}/tests/unit/test_webcompile.py +0 -0
  145. {fastled-1.4.19 → fastled-1.4.33}/upload_package.sh +0 -0
  146. {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
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.4.19
3
+ Version: 1.4.33
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -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.19"
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: not running in FastLED repository")
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 Time: {diff:.2f}\n output: {output_dir}\n hash: {hash_value}\n zip size: {len(web_result.zip_bytes)} bytes"
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 = False
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()
@@ -122,6 +122,9 @@ class FileChangedNotifier(threading.Thread):
122
122
  time.sleep(0.1)
123
123
  except KeyboardInterrupt:
124
124
  print("File watcher stopped by user.")
125
+ import _thread
126
+
127
+ _thread.interrupt_main()
125
128
  finally:
126
129
  self.stop()
127
130
 
@@ -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)