logs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Logs-devel] cl-cli proposal -- defopt


From: Vijay Lakshminarayanan
Subject: Re: [Logs-devel] cl-cli proposal -- defopt
Date: Sun, 25 Jun 2006 18:53:09 -0500

On 6/25/06, Jim Prewett <address@hidden> wrote:

Hello,

I'm thinking a more elegant way to specify a command line option might be
a macro I'm working on called defopt.  Here is an example usage:

(defopt
        ;; the name of the flag is "file"
        "file"
        ;; the flag takes a filename parameter and optional position
        ;; parameter
        (filename &optional position)
        ;; expression (with parameters bound)
        ;; to set up things properly for that flag
        ;; (this is the body of the lambda function)
        (let ((ff
               (make-instance
                'org.prewett.LoGS::File-Follower
                :FileName
                filename)))
                ;; if position is specified, start there
                (when position
                (when (not ff) (error "no ff~%"))
                (org.prewett.LoGS::set-file-follower-position
                 ff
                 (read-from-string position)))
                (push ff *file-list*))
        ;; a list of (optional) aliases for this flag
        :aliases '("f")
        ;; the description of this flag, used in the help text
        :description "file to read from")

Does this look somewhat reasonable?

I'm thinking that by specifying an option this way, the user only has to
specify the argument list once, and in a much more lispy way IMO.

It is better than the old scheme :-)  but I don't like many things.

Also, why not have defopt accept the parameters as keyword arguments?
It makes things clearer and reduces the need for comments.

Something like:
(defopt :name "file" :alias '("f" "ff")
       :params (filename &optional position)
       :action (list filename position))

There are several problems with :action

First, you cannot have recursive functions.  All actions must start
with an explicit progn or a let or block.  Take the case where an
action must start with a DECLARE form.

Also we cannot reuse functions with this syntax.  I think we should
keep the original syntax but instead of strings use sexps.  It doesn't
matter that we are forced to repeat because of the benefits and
freedoms we get as a consequence.

Here are a few examples:

:parameters (one two &optional three)
:actions #'list

:parameters (one two three)
:actions (lambda (&rest args)

Here's an implementation of option-lengths that uses symbols:

(defun option-lengths (option)
 (let ((min-args 0) ; minimum arguments to this flag
       (max-args 0) ; maximum arguments to this flag
       (seen-optional-arg nil) ; has an optional argument been seen?
       (multiargs nil) ; are an infinite number of arguments possible?
       )
   (flet ((specialp (arg)
            (and (symbolp arg) (char= (elt (symbol-name arg) 0) #\&)))
          (special (arg)
            (let ((arg (intern (symbol-name arg))))
              (ecase arg
                (&optional (setq seen-optional-arg t))
                (&rest (setq multiargs t))
                ((&body &key)
                 (error "Cannot support ~a for command line." arg))))))
     (loop as arg in (arguments option)
           if (specialp arg)
           do (special arg)
           else
           do (incf max-args)
           and unless (or seen-optional-arg multiargs)
           do (incf min-args)
           finally (return (if (or multiargs seen-optional-arg)
                               (values min-args max-args)
                               (values min-args ())))))))

While writing this, it occured to me that you could very easily parse
the options that took single options using:
(destructuring-bind (&key foo bar baz) (get-application-args)
 &body)

IMHO there will be places where using a different lambda-list for the
action and the explicit arguments might make life easier for the
programmer.  At the same time, as a lisper, I do think life can be
made simpler with having to specify the arglist only in one place
since that is the majority of how anyone would like it.  Duplicating
the code is also error-prone, I admit.

But I would recommend that we keep the arguments and actions
parameters independant of each other.

Jim
Thanks
Vijay




reply via email to

[Prev in Thread] Current Thread [Next in Thread]