changeset 649: | 6e5006dfe7b8 |
parent: | 74e563ed4537 |
child: | 328e1ff73938 |
author: | Richard Westhaver <ellis@rwest.io> |
date: | Thu, 12 Sep 2024 22:38:22 -0400 |
permissions: | -rw-r--r-- |
description: | clap parsing updates |
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
1 | ;;; cli/clap/cmd.lisp --- Clap Commands |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
2 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
3 | ;; Command Objects used to build CLI Applications. |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
4 | |
560
b9c64be96888
make cli/clap more dynamic
Richard Westhaver <ellis@rwest.io>
parents:
486
diff
changeset
|
5 | ;;; Commentary: |
b9c64be96888
make cli/clap more dynamic
Richard Westhaver <ellis@rwest.io>
parents:
486
diff
changeset
|
6 | |
b9c64be96888
make cli/clap more dynamic
Richard Westhaver <ellis@rwest.io>
parents:
486
diff
changeset
|
7 | ;; |
b9c64be96888
make cli/clap more dynamic
Richard Westhaver <ellis@rwest.io>
parents:
486
diff
changeset
|
8 | |
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
9 | ;;; Code: |
426
3e721a3349a0
completed phase2 of clap migration
Richard Westhaver <ellis@rwest.io>
parents:
419
diff
changeset
|
10 | (in-package :cli/clap/obj) |
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
11 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
12 | (defclass cli-cmd () |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
13 | ;; name slot is required and must be a string |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
14 | ((name :initarg :name :initform (required-argument :name) :accessor cli-name :type string) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
15 | (opts :initarg :opts :initform (make-array 0 :element-type 'cli-opt :adjustable t) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
16 | :accessor cli-opts :type (vector cli-opt)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
17 | (cmds :initarg :cmds :initform (make-array 0 :element-type 'cli-cmd :adjustable t) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
18 | :accessor cli-cmds :type (vector cli-cmd)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
19 | (thunk :initform #'default-thunk :initarg :thunk :accessor cli-thunk :type function-lambda-expression) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
20 | (lock :initform nil :initarg :lock :accessor cli-lock-p :type boolean) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
21 | (description :initarg :description :accessor cli-description :type string) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
22 | (args :initform nil :initarg :args :accessor cli-cmd-args)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
23 | (:documentation "CLI command class inherited by both the 'main' command which is executed when |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
24 | a CLI is called without arguments, and all subcommands.")) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
25 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
26 | (defmethod initialize-instance :after ((self cli-cmd) &key) |
567 | 27 | (with-slots (name thunk opts cmds) self |
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
28 | (unless (stringp name) (setf name (format nil "~(~A~)" name))) |
567 | 29 | (unless (vectorp cmds) (setf cmds (make-cmds cmds))) |
30 | (unless (vectorp opts) (setf opts (make-opts opts))) |
|
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
31 | (when (symbolp thunk) (setf thunk (symbol-function thunk))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
32 | self)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
33 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
34 | (defmethod print-object ((self cli-cmd) stream) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
35 | (print-unreadable-object (self stream :type t) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
36 | (format stream "~A :opts ~A :cmds ~A :args ~A" |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
37 | (cli-name self) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
38 | (length (cli-opts self)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
39 | (length (cli-cmds self)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
40 | (length (cli-cmd-args self))))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
41 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
42 | (defmethod print-usage ((self cli-cmd) &optional stream) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
43 | (with-slots (opts cmds) self |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
44 | (format stream "~(~A~) ~A~A~A" |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
45 | (cli-name self) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
46 | (if-let ((d (and (slot-boundp self 'description) (cli-description self)))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
47 | (format nil ": ~A" d) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
48 | "") |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
49 | (if (null opts) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
50 | "" |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
51 | (format nil "~{~% ~A~^~}" (loop for o across opts collect (print-usage o nil)))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
52 | (if (null cmds) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
53 | "" |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
54 | (format nil "~{!~A~}" (loop for c across cmds collect (print-usage c nil))))))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
55 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
56 | (defmethod push-cmd ((self cli-cmd) (place cli-cmd)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
57 | (vector-push self (cli-cmds place))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
58 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
59 | (defmethod push-opt ((self cli-opt) (place cli-cmd)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
60 | (vector-push self (cli-opts place))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
61 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
62 | (defmethod pop-cmd ((self cli-cmd)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
63 | (vector-pop (cli-cmds self))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
64 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
65 | (defmethod pop-opt ((self cli-opt)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
66 | (vector-pop (cli-opts self))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
67 | |
646
95fd920af398
error handling methods for clap
Richard Westhaver <ellis@rwest.io>
parents:
645
diff
changeset
|
68 | (defmethod handle-unknown-opt ((self cli-cmd) (opt string)) |
95fd920af398
error handling methods for clap
Richard Westhaver <ellis@rwest.io>
parents:
645
diff
changeset
|
69 | (with-opt-restart-case opt |
95fd920af398
error handling methods for clap
Richard Westhaver <ellis@rwest.io>
parents:
645
diff
changeset
|
70 | (clap-unknown-argument opt 'cli-opt))) |
95fd920af398
error handling methods for clap
Richard Westhaver <ellis@rwest.io>
parents:
645
diff
changeset
|
71 | |
95fd920af398
error handling methods for clap
Richard Westhaver <ellis@rwest.io>
parents:
645
diff
changeset
|
72 | (defmethod handle-invalid-opt ((self cli-cmd) (opt string) &optional reason) |
95fd920af398
error handling methods for clap
Richard Westhaver <ellis@rwest.io>
parents:
645
diff
changeset
|
73 | (clap-invalid-argument opt :kind 'cli-opt :reason reason)) |
95fd920af398
error handling methods for clap
Richard Westhaver <ellis@rwest.io>
parents:
645
diff
changeset
|
74 | |
95fd920af398
error handling methods for clap
Richard Westhaver <ellis@rwest.io>
parents:
645
diff
changeset
|
75 | (defmethod handle-missing-opt ((self cli-cmd) (opt string)) |
95fd920af398
error handling methods for clap
Richard Westhaver <ellis@rwest.io>
parents:
645
diff
changeset
|
76 | (clap-missing-argument opt 'cli-opt)) |
95fd920af398
error handling methods for clap
Richard Westhaver <ellis@rwest.io>
parents:
645
diff
changeset
|
77 | |
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
78 | (defmethod cli-equal ((a cli-cmd) (b cli-cmd)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
79 | (with-slots (name opts cmds) a |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
80 | (with-slots ((bn name) (bo opts) (bc cmds)) b |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
81 | (and (string= name bn) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
82 | (if (and (null opts) (null bo)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
83 | t |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
84 | (unless (member nil (loop for oa across opts |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
85 | for ob across bo |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
86 | collect (cli-equal oa ob))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
87 | t)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
88 | (if (and (null cmds) (null bc)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
89 | t |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
90 | (unless (member nil (loop for ca across cmds |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
91 | for cb across bc |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
92 | collect (cli-equal ca cb))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
93 | t)))))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
94 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
95 | (defmethod find-cmd ((self cli-cmd) name &optional active) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
96 | (when-let ((c (find name (cli-cmds self) :key #'cli-name :test #'string=))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
97 | (if active |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
98 | ;; maybe issue warning here? report to user |
647 | 99 | (when (cli-lock-p c) |
100 | c) |
|
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
101 | c))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
102 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
103 | (defmethod active-cmds ((self cli-cmd)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
104 | (remove-if-not #'cli-lock-p (cli-cmds self))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
105 | |
649 | 106 | (defmethod activate-cmd ((self cli-cmd)) |
107 | (setf (cli-lock-p self) t)) |
|
108 | ||
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
109 | (defmethod find-opts ((self cli-cmd) name &key active recurse) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
110 | (let ((ret)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
111 | (flet ((%find (o obj) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
112 | (when-let ((found (find o (cli-opts obj) :key #'cli-opt-name :test 'equal))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
113 | (push found ret)))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
114 | (when (and recurse (cli-cmds self)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
115 | (loop for c across (cli-cmds self) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
116 | do (%find name c))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
117 | (%find name self) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
118 | (when active |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
119 | (setf ret (remove-if-not #'cli-lock-p ret))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
120 | ret))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
121 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
122 | (defmethod active-opts ((self cli-cmd) &optional global) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
123 | (remove-if-not |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
124 | (if global |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
125 | #'active-global-opt-p |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
126 | #'cli-opt-lock) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
127 | (cli-opts self))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
128 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
129 | (defmethod find-short-opts ((self cli-cmd) ch &key recurse) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
130 | (let ((ret)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
131 | (flet ((%find (ch obj) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
132 | (when-let ((found (find ch (cli-opts obj) :key #'cli-opt-name :test #'opt-string-prefix-eq))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
133 | (push found ret)))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
134 | (when (and recurse (cli-cmds self)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
135 | (loop for c across (cli-cmds self) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
136 | do (%find ch c))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
137 | (%find ch self) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
138 | ret))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
139 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
140 | (declaim (inline solop)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
141 | (defun solop (self) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
142 | (and (= 0 (length (active-cmds self)) (length (active-opts self))))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
143 | |
645 | 144 | (defmacro with-opt-restart-case (arg condition) |
145 | "Bind restarts 'use-as-arg' and 'discard-arg' for duration of BODY." |
|
146 | `(restart-case ,condition |
|
147 | (use-as-arg () () (make-cli-node 'arg ,arg)) |
|
647 | 148 | (discard-arg () () (setf ,arg nil)))) |
645 | 149 | |
426
3e721a3349a0
completed phase2 of clap migration
Richard Westhaver <ellis@rwest.io>
parents:
419
diff
changeset
|
150 | (defmethod proc-args ((self cli-cmd) args) |
3e721a3349a0
completed phase2 of clap migration
Richard Westhaver <ellis@rwest.io>
parents:
419
diff
changeset
|
151 | "Process ARGS into an ast. Each element of the ast is a node with a |
3e721a3349a0
completed phase2 of clap migration
Richard Westhaver <ellis@rwest.io>
parents:
419
diff
changeset
|
152 | :kind slot, indicating the type of node and a :form slot which stores |
647 | 153 | a value." |
426
3e721a3349a0
completed phase2 of clap migration
Richard Westhaver <ellis@rwest.io>
parents:
419
diff
changeset
|
154 | (make-cli-ast |
649 | 155 | (loop |
156 | with skip |
|
157 | for i below (length args) |
|
158 | for (a . args) on args |
|
159 | if skip |
|
160 | do (setq skip nil) |
|
161 | else if (short-opt-p a) ;; SHORT OPT |
|
162 | collect |
|
163 | (if-let ((o (car (find-short-opts self (aref a 1) :recurse t)))) |
|
164 | (%compose-short-opt o) |
|
165 | ;; TODO 2024-09-11: signal error? |
|
166 | (with-opt-restart-case a |
|
167 | (clap-unknown-argument a))) |
|
168 | else if (long-opt-p a) ;; LONG OPT |
|
169 | collect |
|
170 | (let ((o (car (find-opts self (string-left-trim "-" a) :recurse t))) |
|
171 | (has-eq (long-opt-has-eq-p a))) |
|
172 | (cond |
|
173 | ((and has-eq o) |
|
174 | (setf (cli-opt-val o) (cdr has-eq)) |
|
175 | (make-cli-node 'opt o)) |
|
176 | ((and (not has-eq) o) |
|
177 | (prog1 |
|
178 | (%compose-long-opt o (pop args)) |
|
179 | (setq skip t))) |
|
180 | (t ;; (not o) (not has-eq) |
|
645 | 181 | (with-opt-restart-case a |
649 | 182 | (clap-unknown-argument a))))) |
183 | ;; OPT GROUP |
|
184 | else if (opt-group-p a) |
|
185 | collect (make-cli-node 'group nil) |
|
186 | else ;; CMD or ARG |
|
187 | collect |
|
188 | (let ((cmd (find-cmd self a))) |
|
189 | (if cmd |
|
190 | ;; CMD |
|
191 | (make-cli-node 'cmd cmd) |
|
192 | ;; ARG |
|
193 | (make-cli-node 'arg a)))))) |
|
426
3e721a3349a0
completed phase2 of clap migration
Richard Westhaver <ellis@rwest.io>
parents:
419
diff
changeset
|
194 | |
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
195 | (defmethod install-ast ((self cli-cmd) (ast cli-ast)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
196 | "Install the given AST, recursively filling in value slots." |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
197 | (with-slots (cmds opts) self |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
198 | ;; we assume all nodes in the ast have been validated and the ast |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
199 | ;; itself is consumed. validation is performed in proc-args. |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
200 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
201 | ;; before doing anything else we lock SELF, which should remain |
649 | 202 | ;; locked until all subcommands have completed |
203 | (activate-cmd self) |
|
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
204 | (loop named install |
649 | 205 | for (node . tail) on (ast ast) |
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
206 | until (null node) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
207 | do |
426
3e721a3349a0
completed phase2 of clap migration
Richard Westhaver <ellis@rwest.io>
parents:
419
diff
changeset
|
208 | (let ((kind (cli-node-kind node)) (form (cli-node-form node))) |
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
209 | (case kind |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
210 | ;; opts |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
211 | (opt |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
212 | (let ((name (cli-opt-name form))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
213 | (when-let ((o (car (find-opts self name)))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
214 | (setf o form) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
215 | (setf (cli-opt-lock o) t)))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
216 | ;; when we encounter a command we recurse over the tail |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
217 | (cmd |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
218 | (when-let ((c (find-cmd self (cli-name form)))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
219 | ;; handle the rest of the AST |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
220 | (setf c (install-ast c (make-cli-ast tail))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
221 | (return-from install))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
222 | (arg (push-arg form self))))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
223 | (setf (cli-cmd-args self) (nreverse (cli-cmd-args self))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
224 | self)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
225 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
226 | (defmethod install-thunk ((self cli-cmd) (lambda function) &optional compile) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
227 | "Install THUNK into the corresponding slot in cli-cmd SELF." |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
228 | (let ((%thunk (if compile (compile nil lambda) lambda))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
229 | (setf (cli-thunk self) %thunk) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
230 | self)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
231 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
232 | (defmethod push-arg (arg (self cli-cmd)) |
485 | 233 | "Push an ARG onto the corresponding slot of a CLI-CMD." |
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
234 | (push arg (cli-cmd-args self))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
235 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
236 | (defmethod parse-args ((self cli-cmd) args &key (compile t)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
237 | "Parse ARGS and return the updated object SELF. |
485 | 238 | ARGS is assumed to be a valid cli-ast (list of cli-nodes), unless COMPILE is |
239 | t, in which case a list of strings is assumed." |
|
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
240 | (with-slots (opts cmds) self |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
241 | (let ((args (if compile (proc-args self args) args))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
242 | (install-ast self args)))) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
243 | |
626 | 244 | ;; WARNING: make sure to fill in the opt and cmd slots with values |
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
245 | ;; from the top-level args before calling a command. |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
246 | (defmethod call-cmd ((self cli-cmd) args opts) |
485 | 247 | (trace! "calling command:" args opts) |
419
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
248 | (funcall (cli-thunk self) args opts)) |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
249 | |
0f0e5f9b5c55
add emacs/babel.org, finished clap refactor phase 1, test system fixes and more top-level packages
Richard Westhaver <ellis@rwest.io>
parents:
404
diff
changeset
|
250 | (defmethod do-cmd ((self cli-cmd)) |
485 | 251 | "Perform the command, recursively calling child commands and opts if necessary." |
486 | 252 | (loop for o across (active-opts self) |
253 | do (do-opt o)) |
|
254 | (if (solop self) |
|
255 | (call-cmd self (cli-cmd-args self) (active-opts self)) |
|
256 | (loop for c across (active-cmds self) |
|
257 | do (do-cmd c)))) |
|
649 | 258 |