;;;; utils.lisp (in-package :oneliners.cli.app) (defun parse-identifier (str) "If STR holds digits representing an integer, parse them. otherwise return the string. Oneliner identifiers may be names or ID numbers. Returns NIL in the case that STR is NIL" (when str (or (parse-integer str :junk-allowed t) str))) (defvar *cmd* nil) (defmacro defhandler (name args-pattern &body body) "Convenience macro for defining command handlers that take arguments. The args pattern list of forms sutable for passint to destructuring-bind. Also binds *cmd* to the current command, so that you can pass it to getopt forms as needed. E.g. (defhandler moo (a b . more) ...) would become (destructuring-bind. (a b . more) (command-argumets *cmd*) ...) If an error occurs at any time during the execution of BODY, then it is caught and handled by printing the usage statemnnt for the current command. " (let ((cmd-var (gensym "cmd"))) `(defun ,name (,cmd-var) (let ((*cmd* ,cmd-var)) (handler-case (destructuring-bind ,args-pattern (clingon:command-arguments *cmd*) ,@body) (error () (clingon:print-usage-and-exit *cmd* t)))))))