changelog shortlog graph tags branches files raw help

Mercurial > core / changeset: clap parsing updates

changeset 649: 6e5006dfe7b8
parent 648: 926d95e5fdc7
child 650: 692dfd7f02d0
author: Richard Westhaver <ellis@rwest.io>
date: Thu, 12 Sep 2024 22:38:22 -0400
files: lisp/lib/cli/clap/cmd.lisp lisp/lib/cli/clap/opt.lisp lisp/lib/cli/clap/pkg.lisp lisp/lib/cli/clap/proto.lisp lisp/lib/cli/clap/util.lisp lisp/lib/cli/multi.lisp lisp/lib/cli/pkg.lisp
description: clap parsing updates
     1.1--- a/lisp/lib/cli/clap/cmd.lisp	Thu Sep 12 16:48:47 2024 -0400
     1.2+++ b/lisp/lib/cli/clap/cmd.lisp	Thu Sep 12 22:38:22 2024 -0400
     1.3@@ -103,6 +103,9 @@
     1.4 (defmethod active-cmds ((self cli-cmd))
     1.5   (remove-if-not #'cli-lock-p (cli-cmds self)))
     1.6 
     1.7+(defmethod activate-cmd ((self cli-cmd))
     1.8+  (setf (cli-lock-p self) t))
     1.9+
    1.10 (defmethod find-opts ((self cli-cmd) name &key active recurse)
    1.11   (let ((ret))
    1.12     (flet ((%find (o obj)
    1.13@@ -149,52 +152,45 @@
    1.14 :kind slot, indicating the type of node and a :form slot which stores
    1.15 a value."
    1.16   (make-cli-ast
    1.17-   (let ((holes)) ;; list of arg indexes which can be skipped since they're
    1.18-                  ;; consumed by an opt
    1.19-     (loop 
    1.20-       for i below (length args)
    1.21-       for (a . args) on args
    1.22-       if (member i holes)
    1.23-         do (continue) ;; skip args which have been consumed already
    1.24-       ;; else
    1.25-       ;;   if (= (length a) 1)
    1.26-       ;;     collect (make-cli-node 'arg a) ; always treat single-char as arg
    1.27-       else
    1.28-         if (short-opt-p a) ;; SHORT OPT
    1.29-           collect
    1.30-           (if-let ((o (find-short-opts self (aref a 1) :recurse t)))
    1.31-             (%compose-short-opt (car o) a)
    1.32-             ;;  TODO 2024-09-11: signal error?
    1.33+   (loop
    1.34+     with skip
    1.35+     for i below (length args)
    1.36+     for (a . args) on args
    1.37+     if skip
    1.38+     do (setq skip nil)
    1.39+     else if (short-opt-p a) ;; SHORT OPT
    1.40+     collect
    1.41+        (if-let ((o (car (find-short-opts self (aref a 1) :recurse t))))
    1.42+          (%compose-short-opt o)
    1.43+          ;;  TODO 2024-09-11: signal error?
    1.44+          (with-opt-restart-case a
    1.45+            (clap-unknown-argument a)))
    1.46+     else if (long-opt-p a) ;; LONG OPT
    1.47+     collect           
    1.48+        (let ((o (car (find-opts self (string-left-trim "-" a) :recurse t)))
    1.49+              (has-eq (long-opt-has-eq-p a)))
    1.50+          (cond
    1.51+            ((and has-eq o)
    1.52+             (setf (cli-opt-val o) (cdr has-eq))
    1.53+             (make-cli-node 'opt o))
    1.54+            ((and (not has-eq) o)
    1.55+             (prog1
    1.56+                 (%compose-long-opt o (pop args))
    1.57+               (setq skip t)))
    1.58+            (t ;; (not o) (not has-eq)
    1.59              (with-opt-restart-case a
    1.60-               (clap-unknown-argument a)))
    1.61-       else
    1.62-         if (long-opt-p a) ;; LONG OPT
    1.63-           collect           
    1.64-             (let ((o (find-opts self (string-left-trim "-" a) :recurse t))
    1.65-                   (has-eq (long-opt-has-eq-p a)))
    1.66-               (cond
    1.67-                 ((and has-eq o)
    1.68-                  (setf (cli-opt-val o) (cdr has-eq))
    1.69-                  (make-cli-node 'opt o))
    1.70-                 ((and (not has-eq) o)
    1.71-                  (prog1 (%compose-long-opt (car o) args)
    1.72-                    (push (1+ i) holes)))
    1.73-                 (t ;; (not o) (not has-eq)
    1.74-                  (with-opt-restart-case a
    1.75-                    (clap-unknown-argument a)))))
    1.76-           ;; OPT GROUP
    1.77-       else 
    1.78-         if (opt-group-p a)
    1.79-           collect nil
    1.80-       ;; CMD
    1.81-       else 
    1.82-         collect
    1.83-         (let ((cmd (find-cmd self a)))
    1.84-           (if cmd
    1.85-               ;; TBD
    1.86-               (make-cli-node 'cmd (find-cmd self a))
    1.87-               ;; ARG
    1.88-               (make-cli-node 'arg a)))))))
    1.89+               (clap-unknown-argument a)))))
    1.90+     ;; OPT GROUP
    1.91+     else if (opt-group-p a)
    1.92+     collect (make-cli-node 'group nil)
    1.93+     else ;; CMD or ARG
    1.94+     collect
    1.95+        (let ((cmd (find-cmd self a)))
    1.96+          (if cmd
    1.97+              ;; CMD
    1.98+              (make-cli-node 'cmd cmd)
    1.99+              ;; ARG
   1.100+              (make-cli-node 'arg a))))))
   1.101 
   1.102 (defmethod install-ast ((self cli-cmd) (ast cli-ast))
   1.103   "Install the given AST, recursively filling in value slots."
   1.104@@ -203,10 +199,10 @@
   1.105     ;; itself is consumed. validation is performed in proc-args.
   1.106 
   1.107     ;; before doing anything else we lock SELF, which should remain
   1.108-    ;; locked for the full runtime duration.
   1.109-    (setf (cli-lock-p self) t)
   1.110+    ;; locked until all subcommands have completed
   1.111+    (activate-cmd self)
   1.112     (loop named install
   1.113-          for (node . tail) on (debug! (ast ast))
   1.114+          for (node . tail) on (ast ast)
   1.115           until (null node)
   1.116           do 
   1.117              (let ((kind (cli-node-kind node)) (form (cli-node-form node)))
   1.118@@ -259,4 +255,4 @@
   1.119       (call-cmd self (cli-cmd-args self) (active-opts self))
   1.120       (loop for c across (active-cmds self)
   1.121             do (do-cmd c))))
   1.122-  
   1.123+
     2.1--- a/lisp/lib/cli/clap/opt.lisp	Thu Sep 12 16:48:47 2024 -0400
     2.2+++ b/lisp/lib/cli/clap/opt.lisp	Thu Sep 12 22:38:22 2024 -0400
     2.3@@ -42,14 +42,15 @@
     2.4   (description nil :type (or null string))
     2.5   (lock nil :type boolean))
     2.6 
     2.7-(defun %compose-short-opt (o arg)
     2.8-  (declare (ignorable arg))
     2.9+(defmethod activate-opt ((self cli-opt))
    2.10+  (setf (cli-lock-p self) t))
    2.11+
    2.12+(defun %compose-short-opt (o)
    2.13   (setf (cli-opt-val o) t)
    2.14   (make-cli-node 'opt o))
    2.15 
    2.16-(defun %compose-long-opt (o args)
    2.17-  (declare (ignorable args))
    2.18-  (setf (cli-opt-val o) (or (pop args) t))
    2.19+(defun %compose-long-opt (o &optional val)
    2.20+  (setf (cli-opt-val o) val)
    2.21   (make-cli-node 'opt o))
    2.22 
    2.23 (defmethod handle-unknown-argument ((self cli-opt) arg))
     3.1--- a/lisp/lib/cli/clap/pkg.lisp	Thu Sep 12 16:48:47 2024 -0400
     3.2+++ b/lisp/lib/cli/clap/pkg.lisp	Thu Sep 12 22:38:22 2024 -0400
     3.3@@ -41,7 +41,9 @@
     3.4    :handle-missing-arg
     3.5    :handle-invalid-arg
     3.6    :clap-missing-argument
     3.7-   :clap-invalid-argument))
     3.8+   :clap-invalid-argument
     3.9+   :activate-cmd
    3.10+   :activate-opt))
    3.11 
    3.12 (defpackage :cli/clap/ast
    3.13   (:use :cl :std :log :dat/sxp)
    3.14@@ -58,7 +60,8 @@
    3.15    :parse-form-opt :parse-list-op :parse-sym-op :parse-key-op
    3.16    :pasre-num-op :parse-file-op :parse-dir-op :cli
    3.17    :cli-cd :with-cli :opts :cmds :debug-opts
    3.18-   :cli-opt :cli-cmd :cli-opt-val :cli-opt-lock :cli-opt-name))
    3.19+   :cli-opt :cli-cmd :cli-opt-val :cli-opt-lock :cli-opt-name
    3.20+   :active-cmds))
    3.21 
    3.22 (defpackage :cli/clap/simple
    3.23   (:use :cl :std :log :sb-ext)
     4.1--- a/lisp/lib/cli/clap/proto.lisp	Thu Sep 12 16:48:47 2024 -0400
     4.2+++ b/lisp/lib/cli/clap/proto.lisp	Thu Sep 12 22:38:22 2024 -0400
     4.3@@ -41,6 +41,10 @@
     4.4 
     4.5 (defgeneric active-opts (self &optional global))
     4.6 
     4.7+(defgeneric activate-opt (self))
     4.8+
     4.9+(defgeneric activate-cmd (self))
    4.10+
    4.11 (defgeneric find-short-opts (self ch &key))
    4.12 
    4.13 (defgeneric call-opt (self arg))
     5.1--- a/lisp/lib/cli/clap/util.lisp	Thu Sep 12 16:48:47 2024 -0400
     5.2+++ b/lisp/lib/cli/clap/util.lisp	Thu Sep 12 22:38:22 2024 -0400
     5.3@@ -14,8 +14,8 @@
     5.4 
     5.5 (defun long-opt-p (str)
     5.6   (declare (simple-string str))
     5.7-  (and (char= (aref str 0) (aref str 1) #\-)
     5.8-       (> (length str) 2)))
     5.9+  (and (> (length str) 2)
    5.10+       (char= (aref str 0) (aref str 1) #\-)))
    5.11 
    5.12 (defun long-opt-has-eq-p (str)
    5.13   "Return non-nil if STR is a long-opt which has an '=' somewhere,
    5.14@@ -27,8 +27,8 @@
    5.15 (defun short-opt-p (str)
    5.16   (declare (simple-string str))
    5.17   (and (char= (aref str 0) #\-)
    5.18-       (not (char= (aref str 1) #\-))
    5.19-       (> (length str) 1)))
    5.20+       (> (length str) 1)
    5.21+       (not (char= (aref str 1) #\-))))
    5.22 
    5.23 (defun opt-group-p (str)
    5.24   (declare (simple-string str))
     6.1--- a/lisp/lib/cli/multi.lisp	Thu Sep 12 16:48:47 2024 -0400
     6.2+++ b/lisp/lib/cli/multi.lisp	Thu Sep 12 22:38:22 2024 -0400
     6.3@@ -39,9 +39,9 @@
     6.4 When you save an executable lisp image with this function you should
     6.5 arrange for symlinks for each handled value of (ARG0) to be generated
     6.6 ."
     6.7-  `(defmain (:exit ,exit :export ,export)
     6.8-     (string-case ((pathname-name (arg0)) :default ,default)
     6.9-       ,@mains)))
    6.10+  `(cli/clap::defmain (:exit ,exit :export ,export)
    6.11+       (string-case ((pathname-name (arg0)) :default ,default)
    6.12+         ,@mains)))
    6.13 
    6.14 (defun make-symlinks (src &optional directory &rest names)
    6.15   "Make a set of symlinks from SRC to NAMES.
     7.1--- a/lisp/lib/cli/pkg.lisp	Thu Sep 12 16:48:47 2024 -0400
     7.2+++ b/lisp/lib/cli/pkg.lisp	Thu Sep 12 22:38:22 2024 -0400
     7.3@@ -99,7 +99,7 @@
     7.4   (:export :run-emacs :run-emacsclient :org-store-link))
     7.5 
     7.6 (defpackage :cli/multi
     7.7-  (:use :cl :std :cli/clap :cli/repl)
     7.8+  (:use :cl :std)
     7.9   (:export
    7.10    #:define-multi-main
    7.11    #:make-symlinks))