|
1 | 1 | {.used.} |
2 | 2 |
|
3 | 3 | import std/strutils |
| 4 | +from std/sugar import capture, `=>` |
| 5 | +from std/jsffi import JsObject, jsTypeof |
4 | 6 | import ./[cpython, pythonrun,] |
5 | 7 |
|
6 | 8 | import ../Utils/[compat, fileio,] |
@@ -155,25 +157,76 @@ proc pushHistory(prompt: kstring, exp: string) = |
155 | 157 | incomplete.scrollIntoView(ScrollIntoViewOptions( |
156 | 158 | `block`: "start", inline: "start", behavior: "instant")) |
157 | 159 |
|
| 160 | + |
| 161 | +proc runLocalPy(ev: Event, _: VNode) = |
| 162 | + let input = document.createElement("input") |
| 163 | + input.setAttribute("type", "file") |
| 164 | + input.setAttribute("multiple", "") |
| 165 | + input.onchange = proc (e: Event) = |
| 166 | + let fileInput = #[input]# e.target |
| 167 | + |
| 168 | + type |
| 169 | + Promise[T] = ref object of JsObject |
| 170 | + FileList = ref object of JsObject |
| 171 | + File = ref object of Blob |
| 172 | + |
| 173 | + proc len(self: FileList): int {.importjs: "#.length".} |
| 174 | + proc item(self: FileList, idx: int): File {.importcpp.} |
| 175 | + |
| 176 | + proc name(_: File): cstring{.importjs: "#.name".} |
| 177 | + proc text(_: File): Promise[cstring]{.importcpp.} |
| 178 | + |
| 179 | + proc then[T; P: proc](_: Promise[T]; cb: P){.importcpp.} |
| 180 | + |
| 181 | + proc files(_: typeof(fileInput)): FileList{.importjs: "#.files".} |
| 182 | + let inputs = fileInput.files |
| 183 | + #[proc readAsText(_: FileReader, blob: File){.importcpp.} |
| 184 | + # readAsArrayBuffer |
| 185 | + new_FileReader().onload = proc (ev: Event) = |
| 186 | + let t = ev.target#[reader]# |
| 187 | + proc result(_: typeof(t)): cstring{.importjs: "#.result".} |
| 188 | + ...]# |
| 189 | + for i in 0..<inputs.len: |
| 190 | + #reader.readAsText(inputs.item(i)) |
| 191 | + let file = inputs.item(i) |
| 192 | + let filename = $file.name |
| 193 | + capture filename: |
| 194 | + file.text().then((cs: cstring)=>( |
| 195 | + pushHistory(kstring"###>Run File Isolatedly: ", filename); |
| 196 | + let suc = PyRun_SimpleString($cs) |
| 197 | + #TODO: if not suc: ... |
| 198 | + pushHistory(kstring"###>Run File successful: ", $suc) |
| 199 | + redraw() |
| 200 | + )) |
| 201 | + input.click() |
| 202 | + |
158 | 203 | const isEditingClass = "isEditing" |
159 | 204 |
|
| 205 | +proc getInputNode: auto = |
| 206 | + let nodes = document.getElementsByClassName(isEditingClass) |
| 207 | + assert nodes.len == 1, $nodes.len |
| 208 | + let edit = nodes[0] |
| 209 | + edit |
| 210 | + |
160 | 211 | # NOTE: do not use add callback for DOMContentLoaded |
161 | 212 | # as karax's init is called on windows.load event |
162 | 213 | # so to set `clientPostRenderCallback` of setRenderer |
163 | 214 | proc postRenderCallback() = |
164 | 215 | historyNode = document.getElementById(historyContainerId) |
165 | | - |
166 | | - let nodes = document.getElementsByClassName(isEditingClass) |
167 | | - assert nodes.len == 1, $nodes.len |
168 | | - let edit = nodes[0] |
169 | | - edit.focus() |
| 216 | + getInputNode().focus() |
170 | 217 |
|
171 | 218 | const fstdin = "<stdin>" |
172 | 219 | var pyrunner = newPyExecutor fstdin |
173 | 220 |
|
174 | 221 | var prompt: kstring |
175 | 222 | proc createDom(): VNode = |
176 | 223 | result = buildHtml(tdiv): |
| 224 | + tdiv(class="top-menu", style=style( |
| 225 | + (position, kstring"sticky"), |
| 226 | + (top, kstring"0"), # keep always on top |
| 227 | + (display, kstring"flex"), # show children horizontally |
| 228 | + )): |
| 229 | + button(onclick=runLocalPy): text "Run Local .py File" |
177 | 230 | tdiv(class="header"): |
178 | 231 | p(class="info"): |
179 | 232 | text info |
|
0 commit comments