Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Trying to handle parse errors inside run (to use unknown options as free args) #11

@vindarel

Description

@vindarel

Hi,

I've been wanting to parse options in a lenient way, so that unknown options are kept as free args. I found about unknown-option and treat-as-argument, the only issue is that run, which calls parse-command-line, handles everything with a handler-case. So I can't put a handler-bind around run to do my logic.

This is what I want to do:

(handler-bind ((clingon.conditions:unknown-option
                   (lambda (c)
                     (format t "debug: ~a: treating it as a free argument.~&" c)
                     (clingon:treat-as-argument c))))
    (let ((app (top-level/command)))
      (clingon:run app)))

if you replace clingon:run by (clingon:parse-command-line (top-level/command) (list "whatever" "--xyz-unknown-option")) it works.

How could we allow run to be lenient?

option 1: wrap the parsing with handler-bind and add a key argument to the run function to tell how to manage the unknown-option, i.e. modularizing this:

(defmethod run ((top-level command) &optional arguments)
  (handler-case
      (handler-bind ((unknown-option
                       (lambda (c)
                         (treat-as-argument c))))
        (let* ((arguments (or arguments (argv)))
               (cmd (parse-command-line top-level arguments)))
             …

For completeness, we would need to do this for every condition, and change the method signature. Doesn't seem like ideal.

option 2: give the parse-command-line function as argument so I can provide my own.

option 3: I tried to locally override the parse function, with (flet ((clingon.command:parse-command-line (command arguments) …) (clingon:run)), to no avail, it's still using the original one. Maybe I'm doing it wrong.

option 4: copy-paste run and tweak it.

option 5 (brainstorming): somehow extract the parsing from run. We would have a chain of two functions:

(run (parse top/level))

so I could use my parse function:

(run (my-parse top/level))

More context (I'm brainstorming here too): my CLI looks like:

$ tool [options] free-arg

and this free arg names a lisp script that will in turn be loaded and executed.

I want to give more options to this script. I can use "--":

$ tool [options] free-arg -- -a

so far so good. But I managed to be able to call the script directly:

$ ./free-arg

it's still calling tool [options] free-arg under the hood though. This is where I'd like to not use "--", but give it options directly like a real script:

$ ./free-arg -a

if I do this, currently Clingon barks and exits because -a is an unknown option (if it was not defined with the options of tool).

There is the machinery to turn an unknown-option to a free-arg, but I don't see how to do it with run.


The tool is CIEL, I'm trying to ease CL's scripting facilities.

my 2c: https://github.com/vindarel/lisp-maintainers#dnaeon---marin-atanasov-nikolov

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions