@@ -0,0 +1,78 @@
1+(require 'ielm)
2+
3+(defun prybar-config (key)
4+ "Read a Prybar configuration variable from the environment.
5+KEY is a symbol, like `quiet'. Return the value of the
6+environment variable \"PRYBAR_QUIET\" (or analogously for other
7+KEYs). If the environment variable is unset, or its value is the
8+empty string, then return nil instead."
9+ (let* ((name (format "PRYBAR_%s" (upcase (symbol-name key))))
10+ (val (getenv name)))
11+ (and val (/= (length val) 0) val)))
12+
13+(defmacro with-prybar-config (vars &rest body)
14+ "Read Prybar configuration VARS and bind lexically while running BODY.
15+VARS is a list of symbols as could be passed to `prybar-config'.
16+Each symbol is prepended with `prybar-' and bound lexically to
17+the return value of `prybar-config'.
18+
19+VARS may also contain lists of the form (SYMBOL DEFAULT), not
20+just symbols. In this case, the behavior is the same except that
21+DEFAULT is used as the binding for the symbol if `prybar-config'
22+returns nil.
23+
24+For example, the following usage:
25+
26+ (with-prybar-config (eval (ps1 \"-->\"))
27+ ...)
28+
29+expands to:
30+
31+ (let ((prybar-eval (prybar-config 'eval))
32+ (prybar-ps1 (or (prybar-config 'ps1) \"-->\")))
33+ ...)"
34+ (declare (indent 1))
35+ `(let (,@(mapcar
36+ (lambda (var)
37+ (if (listp var)
38+ `(,(intern (format "prybar-%S" (nth 0 var)))
39+ (or (prybar-config ',(nth 0 var))
40+ ,(nth 1 var)))
41+ `(,(intern (format "prybar-%S" var))
42+ (prybar-config ',var))))
43+ vars))
44+ ,@body))
45+
46+(defun prybar-repl ()
47+ "Start a Prybar REPL at the top level. This mutates global state.
48+The REPL uses `ielm', which see. After version information is
49+printed and forms for immediate evaluation or execution are
50+handled, display the IELM buffer and return."
51+ (menu-bar-mode -1)
52+ ;; Disable bold and underline, from
53+ ;; <https://stackoverflow.com/a/2065305/3538165>.
54+ (mapc
55+ (lambda (face)
56+ (set-face-attribute face nil :weight 'normal :underline nil))
57+ (face-list))
58+ ;; IELM only supports PS1, not PS2.
59+ (with-prybar-config
60+ (eval exec (ps1 "--> ") quiet file)
61+ (setq ielm-prompt prybar-ps1)
62+ (with-current-buffer (get-buffer-create "*ielm*")
63+ (if prybar-quiet
64+ (setq ielm-header "")
65+ (insert (format "GNU Emacs %s\n" emacs-version)))
66+ (when prybar-file
67+ (condition-case e
68+ (load (expand-file-name prybar-file) nil 'nomessage)
69+ (error
70+ (insert (format "%s\n" (error-message-string e))))))
71+ (inferior-emacs-lisp-mode)
72+ (when prybar-exec
73+ (insert prybar-exec)
74+ (ielm-send-input 'for-effect))
75+ (when prybar-eval
76+ (insert prybar-eval)
77+ (ielm-send-input)))
78+ (pop-to-buffer-same-window "*ielm*")))