Reflow the note, autoload the client, and three todos
NEXT.md rewrapped to a wider column - a reflow, not a rewrite. The three TODO entries in it are the substance: live disassembly of what is actually installed in a cell, error overlays that vanish on the next thing you do rather than surviving until an evaluation is accepted, and CL-style interactive recovery where a stopped program offers a typed restart and the editor asks for the value before invoking it. flan-mode's declare-functions become real autoloads. A declare-function only quiets the byte compiler; it does not load anything, so a user who had loaded only flan-mode could not invoke M-x flan-dev at all.
This commit is contained in:
parent
a5980734dc
commit
5170746de5
@ -427,9 +427,9 @@ for it — this is only what Emacs is responsible for killing.")
|
||||
SOCKET defaults to `flan-dev-socket-name' beside FILE, which is where the
|
||||
daemon puts it when it is not told otherwise.
|
||||
|
||||
Refuses while a daemon this Emacs started is still alive, by name: killing it
|
||||
would take its program — and everything that program has in memory — with it,
|
||||
which is the one thing a dev loop exists to avoid doing by accident."
|
||||
When called interactively while a daemon this Emacs started is alive, asks
|
||||
before stopping it and switching programs. A noninteractive call still
|
||||
refuses: callers cannot silently discard a running program's state."
|
||||
(interactive
|
||||
;; The program last started, where there was one: a restart after a quit is
|
||||
;; the common case, and it is rarely the buffer point happens to be in —
|
||||
@ -439,8 +439,23 @@ which is the one thing a dev loop exists to avoid doing by accident."
|
||||
(string-suffix-p ".flan" buffer-file-name)
|
||||
(file-name-nondirectory buffer-file-name)))))
|
||||
(when (process-live-p flan-dev--daemon)
|
||||
(user-error "flan dev: already running on %s; M-x flan-dev-quit first"
|
||||
(abbreviate-file-name (or flan-dev--socket "a socket"))))
|
||||
;; `interactive' has already read FILE. Refusing only here used to make
|
||||
;; that selection look as though it had been ignored: the old daemon kept
|
||||
;; running, even though the minibuffer had just accepted a different
|
||||
;; program. Keep the state-preserving default for Lisp callers, but let a
|
||||
;; person explicitly choose to replace their own session.
|
||||
(if (called-interactively-p 'interactive)
|
||||
(if (y-or-n-p
|
||||
(format "Stop %s and start %s? "
|
||||
(abbreviate-file-name
|
||||
(or flan-dev--file "the running program"))
|
||||
(abbreviate-file-name (expand-file-name file))))
|
||||
(flan-dev-quit)
|
||||
(user-error "flan dev: keeping %s"
|
||||
(abbreviate-file-name
|
||||
(or flan-dev--file "the running program"))))
|
||||
(user-error "flan dev: already running on %s; M-x flan-dev-quit first"
|
||||
(abbreviate-file-name (or flan-dev--socket "a socket")))))
|
||||
(let* ((file (expand-file-name file))
|
||||
(socket (or socket
|
||||
(expand-file-name flan-dev-socket-name
|
||||
|
||||
@ -12,21 +12,22 @@
|
||||
;; otherwise be made buffer-local before its own defvar had run.
|
||||
(require 'imenu)
|
||||
|
||||
;; The keymap binds them; loading the client is what defines them, and a user
|
||||
;; may well edit Flan without ever connecting to a running program.
|
||||
(declare-function flan-eval-defun "flan-dev")
|
||||
(declare-function flan-eval-buffer "flan-dev")
|
||||
(declare-function flan-eval-last-sexp "flan-dev")
|
||||
(declare-function flan-connect "flan-dev")
|
||||
(declare-function flan-disconnect "flan-dev")
|
||||
(declare-function flan-describe "flan-dev")
|
||||
(declare-function flan-show-output "flan-dev")
|
||||
(declare-function flan-repl "flan-repl")
|
||||
(declare-function flan-break "flan-dev")
|
||||
(declare-function flan-doc "flan-dev")
|
||||
(declare-function flan-dev "flan-dev")
|
||||
(declare-function flan-dev-quit "flan-dev")
|
||||
(declare-function flan-dev-restart-program "flan-dev")
|
||||
;; The keymap binds them, but do not load the client merely to edit a file.
|
||||
;; These must be real autoloads, not just `declare-function`s: otherwise a
|
||||
;; user who has loaded only flan-mode cannot invoke M-x flan-dev at all.
|
||||
(autoload 'flan-eval-defun "flan-dev" nil t)
|
||||
(autoload 'flan-eval-buffer "flan-dev" nil t)
|
||||
(autoload 'flan-eval-last-sexp "flan-dev" nil t)
|
||||
(autoload 'flan-connect "flan-dev" nil t)
|
||||
(autoload 'flan-disconnect "flan-dev" nil t)
|
||||
(autoload 'flan-describe "flan-dev" nil t)
|
||||
(autoload 'flan-show-output "flan-dev" nil t)
|
||||
(autoload 'flan-repl "flan-repl" nil t)
|
||||
(autoload 'flan-break "flan-dev" nil t)
|
||||
(autoload 'flan-doc "flan-dev" nil t)
|
||||
(autoload 'flan-dev "flan-dev" nil t)
|
||||
(autoload 'flan-dev-quit "flan-dev" nil t)
|
||||
(autoload 'flan-dev-restart-program "flan-dev" nil t)
|
||||
|
||||
(defgroup flan nil
|
||||
"Editing and evaluating Flan."
|
||||
|
||||
21
sand.flan
21
sand.flan
@ -36,8 +36,8 @@
|
||||
;;;; No raylib between here and the next banner, which is what the headless
|
||||
;;;; driver imports this file for. The hash is over exactly this.
|
||||
|
||||
(defconst screen-width 1400)
|
||||
(defconst screen-height 1000)
|
||||
(defconst screen-width 900)
|
||||
(defconst screen-height 600)
|
||||
(defconst cell-size 5)
|
||||
;; f32: velocity is [f32], and there is no implicit widening.
|
||||
(defconst gravity f32 0.05)
|
||||
@ -46,7 +46,7 @@
|
||||
(defconst brush-size 10)
|
||||
|
||||
;; Packed 0xRRGGBBAA. A cell of 0 means empty, so no Option and no tag word.
|
||||
(defconst colors [4 u32] [0xE6B800FF 0x3B6E8CFF 0xA83232FF 0xCC6B1FFF])
|
||||
(defconst colors [4 u32] [0xFFF00FFF 0x3B6E8CFF 0xA83232FF 0xCC6B1FFF])
|
||||
|
||||
;; Flat, unboxed, statically sized. No headers, so these are exactly
|
||||
;; rows*cols*4 bytes each — the same memory the Odin port has. Fixed arrays are
|
||||
@ -283,6 +283,7 @@
|
||||
(when (rl/mouse-button-released? :left) (next-color))
|
||||
(step))
|
||||
|
||||
|
||||
(defn draw-grid []
|
||||
(dotimes [row rows]
|
||||
(dotimes [col cols]
|
||||
@ -438,10 +439,16 @@
|
||||
;; Bare (defn main []) — argv and the i32 status are both optional.
|
||||
;; Nothing in this loop allocates, so context/temp is never even touched.
|
||||
(until (rl/window-should-close?)
|
||||
;; The frame boundary, and the only place a redefinition becomes visible:
|
||||
;; nothing that could be redefined is on the stack here.
|
||||
(agent/poll)
|
||||
(game-update)
|
||||
;; The frame boundary, and the only place a redefinition becomes visible.
|
||||
;; An error while installing/evaluating a dev form, or during the update,
|
||||
;; leaves one CL-style escape hatch: choose `continue' in the editor to
|
||||
;; abandon this frame and return to the next one with the game still live.
|
||||
;; Keep drawing outside it. Skipping between BeginDrawing and EndDrawing
|
||||
;; would leave raylib's frame unbalanced.
|
||||
(restart-case
|
||||
(do (agent/poll)
|
||||
(game-update))
|
||||
(continue [] (do)))
|
||||
(rl/begin-drawing)
|
||||
(game-draw)
|
||||
(rl/end-drawing)))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user