changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/lib/cli/clap/simple.lisp

changeset 698: 96958d3eb5b0
parent: 3e721a3349a0
author: Richard Westhaver <ellis@rwest.io>
date: Fri, 04 Oct 2024 22:04:59 -0400
permissions: -rw-r--r--
description: fixes
1 ;;; cli/clap/simple.lisp --- Clap Simple
2 
3 ;;
4 
5 ;;; Code:
6 (in-package :cli/clap/simple)
7 
8 ;; TODO this is intended to be a simplified functional argument parser
9 ;; which is completely compatible with the toplevel SBCL options.
10 
11 ;; Instead of consuming the args into an AST, we loop over command
12 ;; line options in a lexical context, binding individual symbols.
13 
14 (defun namestring-to-opt (str) (sb-int:symbolicate (string-upcase (trim str :char-bag '(#\-)))))
15 
16 (defvar *default-opt-handlers*
17  (map 'list
18  (lambda (o) (cons (namestring-to-opt o) #'set))
19  sb-impl::+runtime-options+))
20 
21 ;; TODO 2024-03-19: need a way to terminate the loop early. (throw/catch)
22 
23 ;; do handlers need to be able to set multiple symbols?
24 
25 ;; should we define opts as special symbols in their own package? (defpackage :OPTS)
26 (defvar *opt-handlers* *default-opt-handlers*)
27 
28 (defun find-opt-handler (str)
29  (find (namestring-to-opt str) *opt-handlers* :key #'car))
30 
31 (defmacro with-opts-handled (&body body)
32  (let* ((syms (mapcar #'car *opt-handlers*)))
33  `(let ((opts (cdr *posix-argv*))
34  ,@(mapcar #'list syms))
35  (declare (type list opts))
36  (flet (($pop ()
37  (if opts
38  (pop opts)
39  (sb-impl::startup-error "unexpected end of cli opts"))))
40  (loop while opts do
41  (if-let ((opt (find-opt-handler (car opts))))
42  (apply (cdr opt) (car opt) ($pop))))
43  (when *posix-argv*
44  (setf (cdr *posix-argv*) opts))
45  ,@body))))