Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation about extending and adding aliases to pre-existing commands? #4

Closed
4lph4-Ph4un opened this issue Jan 10, 2023 · 10 comments

Comments

@4lph4-Ph4un
Copy link

Hi!

I was wondering how one would add an alias to a pre-existing command? Or for example if I would like to add an option of calling --help with -h, how would that be done?

@4lph4-Ph4un
Copy link
Author

And while I'm at it. How would a developer make a handler call help after specific cases? Let's say after noticing a specific command is used with it's default value?

@dnaeon
Copy link
Owner

dnaeon commented Jan 10, 2023

Hey @4lph4-Ph4un ,

I was wondering how one would add an alias to a pre-existing command?

Not sure I fully understand the question, so can you please provide an example of what you mean by pre-existing command? As in a command provided by a separate package or system, which you want to integrate in your own package?

Or for example if I would like to add an option of calling --help with -h, how would that be done?

The --help and --version flags are bit special, since every command inherits them. If you want to provide a different --help flag with a short-name you can bind the clingon:*default-help-flag* var to your own help option.

And while I'm at it. How would a developer make a handler call help after specific cases? Let's say after noticing a specific command is used with it's default value?

Can you please provide an example usage of this one as well, so I better understand what you mean?

Thanks,
Marin

@4lph4-Ph4un
Copy link
Author

The --help and --version flags are bit special, since every command inherits them. If you want to provide a different --help flag with a short-name you can bind the clingon:default-help-flag var to your own help option.

Actually this clarifies how I get what I want. So I can pretty much overwrite the the flag info with that. Essentially that's what I wanted. Just a way to adjust the default --help command so it functions like originally, BUT has the alternative for invoking it via -h-shorthand!

The second question is how one would make a handler to call the default --help-function on some condition.. like let's say that that I want the CLI-utility I print something first like:
"Hi, it seemed you provided a strange flag for option -x, we managed to calculate stuff, BUT are you entirely sure this is what you wanted? Here's the help"
prints help

I know that example is a bit silly, but I think I'd likely have some usecases where I'd rather give a warning like that along the usage-info, rather than give an error directly!

dnaeon added a commit that referenced this issue Jan 10, 2023
@dnaeon
Copy link
Owner

dnaeon commented Jan 10, 2023

Actually this clarifies how I get what I want. So I can pretty much overwrite the the flag info with that. Essentially that's what I wanted. Just a way to adjust the default --help command so it functions like originally, BUT has the alternative for invoking it via -h-shorthand!

I've just pushed a commit, which exports the vars for default options, so you have easy access to them and bind them as needed.

"Hi, it seemed you provided a strange flag for option -x, we managed to calculate stuff, BUT are you entirely sure this is what you wanted? Here's the help"

I believe what you are looking for are the CLINGON:PRINT-USAGE and CLINGON:PRINT-USAGE-AND-EXIT functions.

Here's an example where I use it in the jingle-demo application to print the usage, if the user didn't specify a sub-command.

Let me know if you have other questions.

@4lph4-Ph4un
Copy link
Author

Hey! That was fast! Huge thanks! I can work with these really well!

@nshan651
Copy link

Hi, Lisp newbie here, would you mind providing an example of how to correctly bind clingon:*default-help-flag*?

I would also like to use "-h" as a shorthand alias for "--help". I've tried using setf like so:

  (setf clingon:*default-help-flag* (clingon:make-option :flag
               :description "Display usage information and exit"
               :long-name "help"
               :short-name #\h
	       :key :clingon.help.flag))

which does seem to update the var as expected:

CL-USER> clingon:*default-help-flag*
#<OPTION-BOOLEAN-TRUE short=h long=help>

However, running my cli executable shows that only the :long-name for help is used, and the -h option is nowhere to be found.

Thank you!

@dnaeon
Copy link
Owner

dnaeon commented Apr 24, 2024

Hey @nshan651 ,

I'll try to provide some example soon, but in the meantime could you please share the full code that you have so far?

@nshan651
Copy link

Thanks so much for the quick response! So for the most relevant bit, I'm following the 3-part options/handler/command workflow as suggested by the documentation:

(defun cli/options ()
  "Returns a list of options for cli command."
  (list
   (clingon:make-option
    :string
    :description "A csv file containing rank choice ballots."
    :short-name #\f
    :long-name "file"
    :key :filename)
   (clingon:make-option
    :string
    :description "Name to greet"
    :short-name #\n
    :long-name "name"
    :env-vars '("USER") 
    :initial-value "lisper"
    :key :name)))

(defun cli/handler (cmd)
  "Handler function for top-level cli command."
  (let ((free-args (clingon:command-arguments cmd))
	(filename (clingon:getopt cmd :filename))
	(name (clingon:getopt cmd :name)))
    (let ((ballots (cl-csv:read-csv (parse-namestring filename)))
	  (candidates (remove-duplicates (reduce #'append ballots :key #'identity)
					 :test #'string=)))
      (format t "~A~%" candidates))))

(defun cli/command ()
  "Command-line entrypoint."
  (clingon:make-command
   :name "rcv"
   :description "Ranked choice voting."
   :version "0.1"
   :authors '("nshan651 <public@nshan651.com")
   :license "GPL-3.0"
   :options (cli/options)
   :handler #'cli/handler))

(defun main ()
  "Program entrypoint."
  (setf clingon:*default-help-flag* (clingon:make-option :flag
               :description "Display usage information and exit"
               :long-name "help"
               :short-name #\h
	       :key :clingon.help.flag))

   (clingon:run (cli/command)))

So upon attempting to update clingon:*default-help-flag* with the previous setf command (which I just threw in my main function before calling clingon:run).

The variable appears to be updated to include a short and a long option in every function context after the main call, but it doesn't seem to get added to the usage printout or the options list.

I didn't attempt to add anything addition to the handler, since I figure --help and --version should already be handled internally.

My full source code is here. Thank you again for your help!

@dnaeon
Copy link
Owner

dnaeon commented Apr 26, 2024

Hey @nshan651 ,

The clingon:*default-help-flag* is actually added to the clingon:*default-options* parameter and added to each command by the (defmethod initialize-instance :after ((command command) &key) method.

So, what you need is to actually set (or bind) clingon:*default-options* to your list of options, e.g.

CL-USER> (let* ((my-help-flag
                  (clingon:make-option :flag
                                       :description "display usage information and exit"
                                       :long-name "help"
                                       :short-name #\h
                                       :key :clingon.help.flag))
                (clingon:*default-options* (list clingon:*default-version-flag*
                                                 clingon:*default-bash-completions-flag*
                                                 my-help-flag)))
           (clingon:make-command
            :name "rcv"
            :description "Ranked choice voting."
            :version "0.1"
            :authors '("nshan651 <public@nshan651.com")
            :license "GPL-3.0"
            :options nil
            :handler nil))
#<CLINGON.COMMAND:COMMAND name=rcv options=3 sub-commands=0>

And then checking the options of this command returns us the new --help flag.

CL-USER> (clingon:command-options *)
(#<CLINGON.OPTIONS:OPTION-BOOLEAN-TRUE short=h long=help>
 #<CLINGON.OPTIONS:OPTION-BOOLEAN-TRUE short=NIL long=bash-completions>
 #<CLINGON.OPTIONS:OPTION-BOOLEAN-TRUE short=NIL long=version>)

If you want to set this once you would do something like this.

CL-USER> (defparameter *my-help-flag*
           (clingon:make-option :flag
                                :description "display usage information and exit"
                                :long-name "help"
                                :short-name #\h
                                :key :clingon.help.flag)
           "My custom help flag")
*MY-HELP-FLAG*
CL-USER> (setf clingon:*default-options*
               (list clingon:*default-version-flag*
                     clingon:*default-bash-completions-flag*
                     *my-help-flag*))
(#<CLINGON.OPTIONS:OPTION-BOOLEAN-TRUE short=NIL long=version>
 #<CLINGON.OPTIONS:OPTION-BOOLEAN-TRUE short=NIL long=bash-completions>
 #<CLINGON.OPTIONS:OPTION-BOOLEAN-TRUE short=h long=help>)

Now every newly created command will use your custom set of default options.

Let me know how it goes, thanks!

@nshan651
Copy link

This is exactly what I was looking for, thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants