1.1--- a/lisp/bin/homer.lisp Tue Oct 01 21:52:17 2024 -0400
1.2+++ b/lisp/bin/homer.lisp Tue Oct 01 22:29:08 2024 -0400
1.3@@ -186,10 +186,10 @@
1.4 :version "0.1.0"
1.5 :description "user home manager"
1.6 :thunk 'homer-check
1.7- :opts ((:name "level" :global t :description "set the log level" :thunk homer-log-level)
1.8- (:name "help" :global t :description "print help" :thunk homer-help)
1.9- (:name "version" :global t :description "print version" :thunk homer-version)
1.10- (:name "force" :global t :description "use force" :thunk homer-force))
1.11+ :opts ((:name "level" :description "set the log level" :thunk homer-log-level)
1.12+ (:name "help" :description "print help" :thunk homer-help)
1.13+ (:name "version" :description "print version" :thunk homer-version)
1.14+ (:name "force" :description "use force" :thunk homer-force))
1.15 :cmds ((:name show :thunk homer-show)
1.16 (:name check :thunk homer-check)
1.17 (:name push :thunk homer-push)
2.1--- a/lisp/bin/organ.lisp Tue Oct 01 21:52:17 2024 -0400
2.2+++ b/lisp/bin/organ.lisp Tue Oct 01 22:29:08 2024 -0400
2.3@@ -37,9 +37,9 @@
2.4 :version "0.0.1"
2.5 :description "org-mode toolbox"
2.6 :thunk 'organ-describe
2.7- :opts ((:name "level" :global t :description "set the log level" :thunk organ-log-level)
2.8- (:name "help" :global t :description "print help" :thunk organ-help)
2.9- (:name "version" :global t :description "print version" :thunk organ-version)
2.10+ :opts ((:name "level" :description "set the log level" :thunk organ-log-level)
2.11+ (:name "help" :description "print help" :thunk organ-help)
2.12+ (:name "version" :description "print version" :thunk organ-version)
2.13 ;; (:name "output" :description "output file" :kind file :thunk organ-output)
2.14 )
2.15 :cmds ((:name inspect
3.1--- a/lisp/bin/packy.lisp Tue Oct 01 21:52:17 2024 -0400
3.2+++ b/lisp/bin/packy.lisp Tue Oct 01 22:29:08 2024 -0400
3.3@@ -16,9 +16,9 @@
3.4 :version "0.1.0"
3.5 :description "Universal Package Manager"
3.6 :thunk 'pk-show
3.7- :opts ((:name "level" :global t :description "set the log level" :thunk pk-log-level)
3.8- (:name "help" :global t :description "print help" :thunk pk-help)
3.9- (:name "version" :global t :description "print version" :thunk pk-version))
3.10+ :opts ((:name "level" :description "set the log level" :thunk pk-log-level)
3.11+ (:name "help" :description "print help" :thunk pk-help)
3.12+ (:name "version" :description "print version" :thunk pk-version))
3.13 :cmds ((:name show
3.14 :opts (:name "target" :thunk pk-target)
3.15 :thunk pk-show)))
4.1--- a/lisp/bin/rdb.lisp Tue Oct 01 21:52:17 2024 -0400
4.2+++ b/lisp/bin/rdb.lisp Tue Oct 01 22:29:08 2024 -0400
4.3@@ -74,10 +74,10 @@
4.4 :version "0.1.0"
4.5 :thunk 'rdb-show
4.6 :description "A simple helper for RocksDB."
4.7- :opts ((:name "level" :global t :description "set the log level" :thunk rdb-log-level)
4.8- (:name "help" :global t :description "print help" :thunk rdb-help)
4.9- (:name "version" :global t :description "print version" :thunk rdb-version)
4.10- (:name "db" :global t :description "target db" :thunk rdb-target-db :kind dir))
4.11+ :opts ((:name "level" :description "set the log level" :thunk rdb-log-level)
4.12+ (:name "help" :description "print help" :thunk rdb-help)
4.13+ (:name "version" :description "print version" :thunk rdb-version)
4.14+ (:name "db" :description "target db" :thunk rdb-target-db :kind dir))
4.15 :cmds ((:name new
4.16 :thunk rdb-new)
4.17 (:name show
4.18@@ -90,9 +90,8 @@
4.19 (defmain start-rdb ()
4.20 (let ((*log-level* :info))
4.21 (with-cli (*rdb-cli* opts cmds args) ()
4.22- (do-opts (active-opts *cli* t))
4.23 (if (active-cmds *cli*)
4.24- (let ((*rdb* (create-db (do-opt (car (find-opts *cli* "db"))))))
4.25+ (rdb:with-db (*rdb* (create-db (do-opt (car (find-opts *cli* "db")))))
4.26 (do-cmd *cli*)
4.27- (close-db *rdb*))
4.28+ (close-db *rdb*))
4.29 (print-help *cli*)))))
5.1--- a/lisp/bin/skel.lisp Tue Oct 01 21:52:17 2024 -0400
5.2+++ b/lisp/bin/skel.lisp Tue Oct 01 22:29:08 2024 -0400
5.3@@ -245,15 +245,15 @@
5.4 ;; :help t
5.5 :description "A hacker's project compiler."
5.6 :thunk skc-show
5.7- :opts ((:name "help" :global t :description "print this message"
5.8+ :opts ((:name "help" :description "print this message"
5.9 :thunk skc-help)
5.10- (:name "version" :global t :description "print version"
5.11+ (:name "version" :description "print version"
5.12 :thunk skc-version)
5.13- (:name "level" :global t :description "set log level (warn,info,debug,trace)"
5.14+ (:name "level" :description "set log level (warn,info,debug,trace)"
5.15 :thunk skc-level)
5.16- (:name "config" :global t :description "set a custom skel user config" :kind file)
5.17- (:name "input" :global t :description "input source" :kind string)
5.18- (:name "output" :global t :description "output target" :kind string))
5.19+ (:name "config" :description "set a custom skel user config" :kind file)
5.20+ (:name "input" :description "input source" :kind string)
5.21+ (:name "output" :description "output target" :kind string))
5.22 :cmds ((:name init
5.23 :description "initialize a skelfile in the current directory"
5.24 :opts (:name "name" :description "project name" :kind string)
5.25@@ -361,6 +361,5 @@
5.26 (setq *skel-project* (load-skelfile project))
5.27 (setq *skel-path* (sk-src *skel-project*))
5.28 (setq cli/shell:*shell-directory* (sk-src *skel-project*))))
5.29- (do-opts *cli* t)
5.30 (do-cmd *cli*)
5.31 (debug-opts *cli*))))
6.1--- a/lisp/lib/cli/clap/cli.lisp Tue Oct 01 21:52:17 2024 -0400
6.2+++ b/lisp/lib/cli/clap/cli.lisp Tue Oct 01 22:29:08 2024 -0400
6.3@@ -48,7 +48,8 @@
6.4 (lambda (x)
6.5 (etypecase x
6.6 (string (make-cli-opt :name x))
6.7- (list (apply #'make-cli :opt x))))
6.8+ (list (apply #'make-cli :opt x))
6.9+ (symbol (make-cli-opt :name (string-downcase (symbol-name x ))))))
6.10 opts))
6.11
6.12 (defun make-cmds (cmds)
7.1--- a/lisp/lib/cli/cli.asd Tue Oct 01 21:52:17 2024 -0400
7.2+++ b/lisp/lib/cli/cli.asd Tue Oct 01 22:29:08 2024 -0400
7.3@@ -42,5 +42,8 @@
7.4 :components ((:module "tests"
7.5 :components
7.6 ((:file "pkg")
7.7- (:file "clap"))))
7.8+ (:file "shell")
7.9+ (:file "ansi")
7.10+ (:file "clap")
7.11+ (:file "tools"))))
7.12 :perform (test-op (o c) (symbol-call :rt :do-tests :cli)))
8.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2+++ b/lisp/lib/cli/tests/ansi.lisp Tue Oct 01 22:29:08 2024 -0400
8.3@@ -0,0 +1,199 @@
8.4+;;; ansi.lisp --- ANSI Tests
8.5+
8.6+;;
8.7+
8.8+;;; Code:
8.9+(in-package :cli/tests)
8.10+(in-suite :cli)
8.11+
8.12+(defun ansi-t01 ()
8.13+ (erase)
8.14+ (cursor-position 0 0)
8.15+ (princ "0")
8.16+ (cursor-position 2 2)
8.17+ (princ "1")
8.18+ (cursor-position 5 15)
8.19+ (princ "test")
8.20+ (cursor-position 10 15)
8.21+ (force-output)
8.22+ (with-input-from-string (in (format nil "test~%~%"))
8.23+ (let ((a (read-line in)))
8.24+ (cursor-position 12 15)
8.25+ (princ a)
8.26+ (force-output))))
8.27+
8.28+(defun ansi-t02 ()
8.29+ (print "normal")
8.30+ (.sgr 1)
8.31+ (print "bold")
8.32+ (.sgr 4)
8.33+ (print "bold underline")
8.34+ (.sgr 7)
8.35+ (print "bold underline reverse")
8.36+ (.sgr 22)
8.37+ (print "underline reverse")
8.38+ (.sgr 24)
8.39+ (print "reverse")
8.40+ (.sgr 27)
8.41+ (print "normal")
8.42+ (.sgr 1 4 7)
8.43+ (print "bold underline reverse")
8.44+ (.sgr 0)
8.45+ (print "normal")
8.46+ (force-output))
8.47+
8.48+(defun ansi-t03 ()
8.49+ "Display the 256 color palette."
8.50+ (clear)
8.51+ (loop for i from 0 to 255 do
8.52+ (.sgr 48 5 i)
8.53+ (princ #\space))
8.54+ (terpri)
8.55+ (.sgr 0)
8.56+ (loop for i from 0 to 255 do
8.57+ (.sgr 38 5 i)
8.58+ (princ "X"))
8.59+ (.sgr 0)
8.60+ (force-output)
8.61+ ;; (sleep 3)
8.62+ (.ris)
8.63+ (force-output))
8.64+
8.65+(defun ansi-t04 ()
8.66+ "Hide and show the cursor."
8.67+ (princ "Cursor visible:")
8.68+ (force-output)
8.69+ ;; (sleep 2)
8.70+ (terpri)
8.71+ (princ "Cursor invisible:")
8.72+ (hide-cursor)
8.73+ (force-output)
8.74+ ;; (sleep 2)
8.75+ (terpri)
8.76+ (princ "Cursor visible:")
8.77+ (show-cursor)
8.78+ (force-output)
8.79+ ;; (sleep 2)
8.80+ )
8.81+
8.82+(defun ansi-t05 ()
8.83+ "Switch to and back from the alternate screen buffer."
8.84+ (princ "Normal screen buffer. ")
8.85+ (force-output)
8.86+ ;; (sleep 2)
8.87+ (save-cursor-position)
8.88+ (use-alternate-screen-buffer)
8.89+ (clear)
8.90+ (princ "Alternate screen buffer.")
8.91+ (force-output)
8.92+ ;; (sleep 2)
8.93+ (use-normal-screen-buffer)
8.94+ (restore-cursor-position)
8.95+ (princ "Back to Normal screen buffer.")
8.96+ (force-output)
8.97+ ;; (sleep 1)
8.98+ )
8.99+
8.100+(defun ansi-t06 ()
8.101+ "Set individual termios flags to enable raw and disable echo mode.
8.102+
8.103+Enabling raw mode allows read-char to return immediately after a key is pressed.
8.104+
8.105+In the default cooked mode, the entry has to be confirmed by pressing enter."
8.106+ (set-tty-mode t :ignbrk nil
8.107+ :brkint nil
8.108+ :parmrk nil
8.109+ :istrip nil
8.110+ :inlcr nil
8.111+ :igncr nil
8.112+ :icrnl nil
8.113+ :ixon nil
8.114+ :opost nil
8.115+ :echo nil
8.116+ :echonl nil
8.117+ :icanon nil
8.118+ :isig nil
8.119+ :iexten nil
8.120+ :csize nil
8.121+ :parenb nil
8.122+ :vmin 1
8.123+ :vtime 0)
8.124+ (erase)
8.125+ (cursor-position 1 1)
8.126+ (force-output)
8.127+ (let ((a (read-char)))
8.128+ (cursor-position 10 5)
8.129+ (princ a)
8.130+ (force-output))
8.131+
8.132+ (set-tty-mode t :echo t
8.133+ :brkint t
8.134+ :ignpar t
8.135+ :istrip t
8.136+ :icrnl t
8.137+ :ixon t
8.138+ :opost t
8.139+ :isig t
8.140+ :icanon t
8.141+ :veol 0))
8.142+
8.143+(defun ansi-t07 ()
8.144+ "Use combination modes that consist of several individual flags.
8.145+
8.146+Cooked and raw are opposite modes. Enabling cooked disbles raw and vice versa."
8.147+ (set-tty-mode t :cooked nil)
8.148+ (erase)
8.149+ (cursor-position 1 1)
8.150+ (force-output)
8.151+ (let ((a (read-char)))
8.152+ (cursor-position 3 1)
8.153+ (princ a)
8.154+ (force-output))
8.155+ (set-tty-mode t :raw nil))
8.156+
8.157+(defun ansi-t08 ()
8.158+ "Why doesnt calling the stty utility work?"
8.159+ (uiop:run-program "stty raw -echo" :ignore-error-status t)
8.160+ (erase)
8.161+ (cursor-position 1 1)
8.162+ (force-output)
8.163+ (let ((a (read-char)))
8.164+ (cursor-position 2 1)
8.165+ (princ a)
8.166+ (force-output))
8.167+ (uiop:run-program "stty -raw echo" :ignore-error-status t))
8.168+
8.169+(defun ansi-t09 ()
8.170+ "Query terminal size with ANSI escape sequences."
8.171+ ;; Put the terminal into raw mode so we can read the "user input"
8.172+ ;; of the reply char by char
8.173+ ;; Turn off the echo or the sequence will be displayed
8.174+ (set-tty-mode t :cooked nil :echo nil)
8.175+ (save-cursor-position)
8.176+ ;; Go to the bottom right corner of the terminal by attempting
8.177+ ;; to go to some high value of row and column
8.178+ (cursor-position 999 999)
8.179+ (let (chars)
8.180+ ;; The terminal returns an escape sequence to the standard input
8.181+ (device-status-report)
8.182+ (force-output)
8.183+ ;; The reply isnt immediately available, the terminal does need
8.184+ ;; some time to answer
8.185+ (sleep 0.1)
8.186+ ;; The reply has to be read as if the user typed an escape sequence
8.187+ (loop for i = (read-char-no-hang *standard-input* nil)
8.188+ until (null i)
8.189+ do (push i chars))
8.190+ ;; Put the terminal back into its initial cooked state
8.191+ (set-tty-mode t :raw nil :echo t)
8.192+ (restore-cursor-position)
8.193+ ;; Return the read sequence as a list of characters.
8.194+ (nreverse chars)))
8.195+
8.196+(deftest ansi ()
8.197+ (with-input-from-string (in (format nil "~%~%"))
8.198+ (ansi-t01)
8.199+ (ansi-t02)
8.200+ (ansi-t03)
8.201+ (ansi-t04)
8.202+ (ansi-t05)))
9.1--- a/lisp/lib/cli/tests/pkg.lisp Tue Oct 01 21:52:17 2024 -0400
9.2+++ b/lisp/lib/cli/tests/pkg.lisp Tue Oct 01 22:29:08 2024 -0400
9.3@@ -7,202 +7,9 @@
9.4 (:use :cl :std :rt :cli :cli/shell :cli/progress :cli/spark :cli/repl :cli/ansi :cli/prompt :cli/clap :cli/tools/sbcl :dat/sxp))
9.5
9.6 (in-package :cli/tests)
9.7-(declaim (optimize (debug 3) (safety 3)))
9.8 (defsuite :cli)
9.9 (in-suite :cli)
9.10
9.11-(defun ansi-t01 ()
9.12- (erase)
9.13- (cursor-position 0 0)
9.14- (princ "0")
9.15- (cursor-position 2 2)
9.16- (princ "1")
9.17- (cursor-position 5 15)
9.18- (princ "test")
9.19- (cursor-position 10 15)
9.20- (force-output)
9.21- (with-input-from-string (in (format nil "test~%~%"))
9.22- (let ((a (read-line in)))
9.23- (cursor-position 12 15)
9.24- (princ a)
9.25- (force-output))))
9.26-
9.27-(defun ansi-t02 ()
9.28- (print "normal")
9.29- (.sgr 1)
9.30- (print "bold")
9.31- (.sgr 4)
9.32- (print "bold underline")
9.33- (.sgr 7)
9.34- (print "bold underline reverse")
9.35- (.sgr 22)
9.36- (print "underline reverse")
9.37- (.sgr 24)
9.38- (print "reverse")
9.39- (.sgr 27)
9.40- (print "normal")
9.41- (.sgr 1 4 7)
9.42- (print "bold underline reverse")
9.43- (.sgr 0)
9.44- (print "normal")
9.45- (force-output))
9.46-
9.47-(defun ansi-t03 ()
9.48- "Display the 256 color palette."
9.49- (clear)
9.50- (loop for i from 0 to 255 do
9.51- (.sgr 48 5 i)
9.52- (princ #\space))
9.53- (terpri)
9.54- (.sgr 0)
9.55- (loop for i from 0 to 255 do
9.56- (.sgr 38 5 i)
9.57- (princ "X"))
9.58- (.sgr 0)
9.59- (force-output)
9.60- ;; (sleep 3)
9.61- (.ris)
9.62- (force-output))
9.63-
9.64-(defun ansi-t04 ()
9.65- "Hide and show the cursor."
9.66- (princ "Cursor visible:")
9.67- (force-output)
9.68- ;; (sleep 2)
9.69- (terpri)
9.70- (princ "Cursor invisible:")
9.71- (hide-cursor)
9.72- (force-output)
9.73- ;; (sleep 2)
9.74- (terpri)
9.75- (princ "Cursor visible:")
9.76- (show-cursor)
9.77- (force-output)
9.78- ;; (sleep 2)
9.79- )
9.80-
9.81-(defun ansi-t05 ()
9.82- "Switch to and back from the alternate screen buffer."
9.83- (princ "Normal screen buffer. ")
9.84- (force-output)
9.85- ;; (sleep 2)
9.86- (save-cursor-position)
9.87- (use-alternate-screen-buffer)
9.88- (clear)
9.89- (princ "Alternate screen buffer.")
9.90- (force-output)
9.91- ;; (sleep 2)
9.92- (use-normal-screen-buffer)
9.93- (restore-cursor-position)
9.94- (princ "Back to Normal screen buffer.")
9.95- (force-output)
9.96- ;; (sleep 1)
9.97- )
9.98-
9.99-(defun ansi-t06 ()
9.100- "Set individual termios flags to enable raw and disable echo mode.
9.101-
9.102-Enabling raw mode allows read-char to return immediately after a key is pressed.
9.103-
9.104-In the default cooked mode, the entry has to be confirmed by pressing enter."
9.105- (set-tty-mode t :ignbrk nil
9.106- :brkint nil
9.107- :parmrk nil
9.108- :istrip nil
9.109- :inlcr nil
9.110- :igncr nil
9.111- :icrnl nil
9.112- :ixon nil
9.113- :opost nil
9.114- :echo nil
9.115- :echonl nil
9.116- :icanon nil
9.117- :isig nil
9.118- :iexten nil
9.119- :csize nil
9.120- :parenb nil
9.121- :vmin 1
9.122- :vtime 0)
9.123- (erase)
9.124- (cursor-position 1 1)
9.125- (force-output)
9.126- (let ((a (read-char)))
9.127- (cursor-position 10 5)
9.128- (princ a)
9.129- (force-output))
9.130-
9.131- (set-tty-mode t :echo t
9.132- :brkint t
9.133- :ignpar t
9.134- :istrip t
9.135- :icrnl t
9.136- :ixon t
9.137- :opost t
9.138- :isig t
9.139- :icanon t
9.140- :veol 0))
9.141-
9.142-(defun ansi-t07 ()
9.143- "Use combination modes that consist of several individual flags.
9.144-
9.145-Cooked and raw are opposite modes. Enabling cooked disbles raw and vice versa."
9.146- (set-tty-mode t :cooked nil)
9.147- (erase)
9.148- (cursor-position 1 1)
9.149- (force-output)
9.150- (let ((a (read-char)))
9.151- (cursor-position 3 1)
9.152- (princ a)
9.153- (force-output))
9.154- (set-tty-mode t :raw nil))
9.155-
9.156-(defun ansi-t08 ()
9.157- "Why doesnt calling the stty utility work?"
9.158- (uiop:run-program "stty raw -echo" :ignore-error-status t)
9.159- (erase)
9.160- (cursor-position 1 1)
9.161- (force-output)
9.162- (let ((a (read-char)))
9.163- (cursor-position 2 1)
9.164- (princ a)
9.165- (force-output))
9.166- (uiop:run-program "stty -raw echo" :ignore-error-status t))
9.167-
9.168-(defun ansi-t09 ()
9.169- "Query terminal size with ANSI escape sequences."
9.170- ;; Put the terminal into raw mode so we can read the "user input"
9.171- ;; of the reply char by char
9.172- ;; Turn off the echo or the sequence will be displayed
9.173- (set-tty-mode t :cooked nil :echo nil)
9.174- (save-cursor-position)
9.175- ;; Go to the bottom right corner of the terminal by attempting
9.176- ;; to go to some high value of row and column
9.177- (cursor-position 999 999)
9.178- (let (chars)
9.179- ;; The terminal returns an escape sequence to the standard input
9.180- (device-status-report)
9.181- (force-output)
9.182- ;; The reply isnt immediately available, the terminal does need
9.183- ;; some time to answer
9.184- (sleep 0.1)
9.185- ;; The reply has to be read as if the user typed an escape sequence
9.186- (loop for i = (read-char-no-hang *standard-input* nil)
9.187- until (null i)
9.188- do (push i chars))
9.189- ;; Put the terminal back into its initial cooked state
9.190- (set-tty-mode t :raw nil :echo t)
9.191- (restore-cursor-position)
9.192- ;; Return the read sequence as a list of characters.
9.193- (nreverse chars)))
9.194-
9.195-(deftest ansi ()
9.196- (with-input-from-string (in (format nil "~%~%"))
9.197- (ansi-t01)
9.198- (ansi-t02)
9.199- (ansi-t03)
9.200- (ansi-t04)
9.201- (ansi-t05)))
9.202-
9.203 ;; TODO: needs to be compiled outside scope of test - contender for
9.204 ;; fixture API
9.205 (defprompt tpfoo :prompt "testing:")
10.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2+++ b/lisp/lib/cli/tests/shell.lisp Tue Oct 01 22:29:08 2024 -0400
10.3@@ -0,0 +1,13 @@
10.4+;;; shell.lisp --- Shell Reader Tests
10.5+
10.6+;;
10.7+
10.8+;;; Code:
10.9+(in-package :cli/tests)
10.10+(in-suite :cli)
10.11+
10.12+(defparameter *shell-test-fn* #$ls #,*default-pathname-defaults* $#)
10.13+
10.14+(deftest shell-reader ()
10.15+ (in-readtable :shell)
10.16+ (is (functionp *shell-test-fn*)))
11.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2+++ b/lisp/lib/cli/tests/tools.lisp Tue Oct 01 22:29:08 2024 -0400
11.3@@ -0,0 +1,11 @@
11.4+;;; tools.lisp --- Tool Tests
11.5+
11.6+;;
11.7+
11.8+;;; Code:
11.9+(in-package :cli/tests)
11.10+(in-suite :cli)
11.11+
11.12+(deftest sbcl ()
11.13+ (with-sbcl (:noinform t :quit t)
11.14+ (print 1)))
12.1--- a/lisp/lib/rdb/macs.lisp Tue Oct 01 21:52:17 2024 -0400
12.2+++ b/lisp/lib/rdb/macs.lisp Tue Oct 01 22:29:08 2024 -0400
12.3@@ -34,14 +34,16 @@
12.4 ;; (rocksdb-destroy-db ,opt ,db-path err) ;; when :destroy only
12.5 (rocksdb-options-destroy ,opt)))))
12.6
12.7-(defmacro with-db ((db-var db) &body body)
12.8+(defmacro with-db ((db-var db &key open close) &body body)
12.9 "Bind DB-VAR to the database object DB for the lifetime of BODY."
12.10 `(let ((,db-var ,db))
12.11 (handler-bind ((error (lambda (condition)
12.12 (error 'rdb-error
12.13 :message
12.14 (format nil "WITH-DB signaled: ~A" condition)))))
12.15- ,@body)))
12.16+ ,@(when open `(open-db ,db-var))
12.17+ ,@(if close `(unwind-protect (progn ,@body) (close ,db-var))
12.18+ body))))
12.19
12.20 ;;; cf
12.21 (defmacro with-cf ((cf-var cf) &body body)