A Simple and Clear CLI library. Dependency free.


A Simple and Clear CLI library. Dependency free.

Awesome CodeFactor CodeFactor

Features

  • Nested Subcommands
  • Uses the standard library flag package
  • Auto-generated help
  • Custom banners
  • Hidden Subcommands
  • Default Subcommand
  • Dependency free

Example

package main

import (
   "fmt"
   "log"

	"github.com/leaanthony/clir"
)

func main() {

	// Create new cli
	cli := clir.NewCli("Flags", "A simple example", "v0.0.1")

	// Name
	name := "Anonymous"
	cli.StringFlag("name", "Your name", &name)

	// Define action for the command
	cli.Action(func() error {
		fmt.Printf("Hello %s!\n", name)
		return nil
	})

	if err := cli.Run(); err != nil {
		fmt.Printf("Error encountered: %v\n", err)
	}

}

Generated Help

$ flags --help
Flags v0.0.1 - A simple example

Flags:

  -help
        Get help on the 'flags' command.
  -name string
        Your name

Documentation

The main documentation may be found here.

License Status

FOSSA Status

Comments
  • feat: custom errors on flags (#16)

    feat: custom errors on flags (#16)

    #16 In the end I decided to go a bit more radical.

    I removed the c.PrintHelp() on flags completely. Most CLIs on wrong flag they output a. the error message b. a suggestion to run the --help flag.

    I also included an example.

    without the custom err

    $ go run ./examples/custom-flag-error/ -w
    Error: flag provided but not defined: -w
    See 'Flag --help' for usage
    

    with it

    $ go run ./examples/custom-flag-error/ -w
    Error: flag provided but not defined: -w
    Flag v0.0.1 - A custom error example
    
    Flags:
    
      --help
            Get help on the 'flag' command.
    

    the change is "radical" from the perspective of this package but I think it's worth it! :)

    taken from the examples folder:

    func customFlagError(cli *clir.Cli) string {
    	return `Flag v0.0.1 - A custom error example
    Flags:
      --help
    	Get help on the 'flag' command.`
    }
    
    func main() {
    
    	// Create new cli
    	cli := clir.NewCli("Flag", "A custom error example", "v0.0.1")
    
    	cli.SetFlagFunction(customFlagError)
    
    	// Run!
    	if err := cli.Run(); err != nil {
    		fmt.Println(err)
    	}
    
    }
    
  • New feature: add Action callback defined outside of main

    New feature: add Action callback defined outside of main

    I love using CLIR to build simple CLI apps. This change was designed to allow a user to add an Action using a function declared outside of the main() function. Previously, it was not possible to call a function that took any arguments if it was declared outside of main(). Now it is possible to call a function and pass pointers to it that allow the user to access the value of command line arguments.

    Most of the changes are to action.go and they extend the definition of Action. I made use of the reflect package to implement this generic functionality.

    I added the modular example as a proof of concept. To run the example code, the import statement has to be changed to the fork. I made this change because it allowed me to separate my application code from my CLI definition.

    Thank you for the great project @leaanthony, please let me know of any comments or questions

  • Feature: Add Required and Shortcut

    Feature: Add Required and Shortcut

    This is obviously a large change, but add Shortcuts and Required commands that allow the user to set shortcut commands/flags and to mark a command/flag as required.

    CommandRequired() FlagRequired(flagName string) CommandShortCut(cmdShortCut string) FlagShortCut(flagLongName string, flagShortCut string)

    A bunch of examples are in the folder (required, shortcut, and advanced). The advanced example just ties a lot of things together showing some advanced usage. I've run a lot of commands through the code and after a few tweaks I think everything is working as expected. Haven't really done testing in golang before but can look at adding some test statements.

    To the "main loop" I've added code to convert command and flag shortcuts (runs over ALL args as a precaution for both flags and commands, but perhaps just need to test args[0] for commands)

    I then added a function call in the main loop called checkRequired, this checks all of the args to see what flags/commands were specified vs what commands/flags are required. It then prints out the error(s) for missing flags/commands.

    No external libraries were added, but "text/tabwriter" was added to format my portion of the help output.

  • Why yet-another-CLI-framework™?

    Why yet-another-CLI-framework™?

    Hey,

    your package looks promising in my eyes, I especially like the logo. However it is not clear to me, what the benefits of this yet-another-CLI-framework™ in comparsion to other cli-frameworks like commandeer or cobra are. Could you explain them a little bit?

  • Shortcode

    Shortcode

    If you are interested I have implemented a "shortcut" function for commands and flags.

    Essentially allow you define a main flag/shortcut as ("name") and then define a shortcut ("n"), and both will work when called from the command line. There are two commands FlagShortCut and CommandShortCut

    It works like this (for flags, same thing for commands):

            var name string
    	nameFlag := cli.StringFlag("name", "Your name", &name)
    	// FlagShort is used to set a shortcut for a flag. Create a shortcut for "-name", that will be "-n"
    	nameFlag.FlagShortCut("name", "n")
    

    Problems:

    • User could in theory accidentally set a flag shortcut on a command and the other way around
    • The print command for flags cannot show the shortcodes in the same interface unless we rip out the printdefaults from the standard library and implement it in the clir code. We could also add another section after the flags with the shortcodes, but not the nicest way of doing it. Update: Added a print function to print the shortcuts after the flags since that is the easiest way.
    • The commands print has an extra space if no shortcode is set on the command, that is easy to fix with an if check if needed.
  • update example in README

    update example in README

    Update README's example to show that the library user is required to process the error response from the cli.Run() function if they wish to know about any errors.

  • custom flag errors + PrintHelp() suppression

    custom flag errors + PrintHelp() suppression

    As it stands the behaviour of the library when user inputs undefined flags is to print a. the error b. help.

    While the above described approach is thoughtful default behaviour and I could achieve parity with say kubectl or docker or git for non existent commands like so

    	cli.Action(func() error {
    		w := cli.OtherArgs()
    		return fmt.Errorf(`unknown command %q for %q
    Run '%[2]s --help' for usage`, w[0], cli.Name())
    	})
    
    	if err := cli.Run(); err != nil {
    		fmt.Printf("Error: %s\n", err)
    	}
    
    $ go run ./cmd/pilates wrong
    Error: unknown command "wrong" for "pilates"
    Run 'pilates --help' for usage
    

    if I attempt to run $ go run ./cmd/pilates -w I can not suppress the help being printed or return custom messages. Maybe worse the error is hardcoded so I end up with the error printed twice without me being able to stop it.

    $ go run ./cmd/pilates -w
    Error: flag provided but not defined: -w  <--- #1 
    
     Pilates
         v0.0.1 - Ultimate Pilates Machine
    
    Flags:
    
      -help
            Get help on the 'pilates' command.
    
    Error: flag provided but not defined: -w   <--- #2
    

    my proposal is all or anything of the following:

    a. have an option to suppress printing help on undefined flags.

    cli.SuppresHelp()
    

    b. custom undefined flag errors. Return golang err followed by a custom error message. examples:

    $ git -w
    unknown option: -w
    usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
               [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
               [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
               [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
               <command> [<args>]
    

    or

    $ kubectl -w
    Error: unknown shorthand flag: 'w' in -w
    See 'kubectl --help' for usage.
    

    c. fix what seems to be buggy behaviour in line 83 command.go by removing the fmt.Print. https://github.com/leaanthony/clir/blob/3b847b276c5042f799993c62d1219896677c2d26/command.go#L83

  • coverage + CI

    coverage + CI

    PASS
    coverage: 97.6% of statements
    ok      github.com/leaanthony/clir      0.011s
    github.com/leaanthony/clir/cli.go:19:           Version                 100.0%
    github.com/leaanthony/clir/cli.go:24:           Name                    100.0%
    github.com/leaanthony/clir/cli.go:29:           ShortDescription        100.0%
    github.com/leaanthony/clir/cli.go:35:           SetBannerFunction       100.0%
    github.com/leaanthony/clir/cli.go:40:           Abort                   0.0%
    github.com/leaanthony/clir/cli.go:46:           AddCommand              100.0%
    github.com/leaanthony/clir/cli.go:51:           PrintBanner             100.0%
    github.com/leaanthony/clir/cli.go:57:           PrintHelp               100.0%
    github.com/leaanthony/clir/cli.go:62:           Run                     100.0%
    github.com/leaanthony/clir/cli.go:77:           DefaultCommand          100.0%
    github.com/leaanthony/clir/cli.go:83:           NewSubCommand           100.0%
    github.com/leaanthony/clir/cli.go:88:           PreRun                  100.0%
    github.com/leaanthony/clir/cli.go:93:           BoolFlag                100.0%
    github.com/leaanthony/clir/cli.go:99:           StringFlag              100.0%
    github.com/leaanthony/clir/cli.go:105:          IntFlag                 100.0%
    github.com/leaanthony/clir/cli.go:111:          Action                  100.0%
    github.com/leaanthony/clir/cli.go:117:          LongDescription         100.0%
    github.com/leaanthony/clir/clir.go:8:           defaultBannerFunction   100.0%
    github.com/leaanthony/clir/clir.go:13:          NewCli                  100.0%
    github.com/leaanthony/clir/command.go:29:       NewCommand              100.0%
    github.com/leaanthony/clir/command.go:40:       setParentCommandPath    100.0%
    github.com/leaanthony/clir/command.go:55:       setApp                  100.0%
    github.com/leaanthony/clir/command.go:60:       parseFlags              100.0%
    github.com/leaanthony/clir/command.go:70:       run                     95.0%
    github.com/leaanthony/clir/command.go:119:      Action                  100.0%
    github.com/leaanthony/clir/command.go:125:      PrintHelp               100.0%
    github.com/leaanthony/clir/command.go:167:      isDefaultCommand        100.0%
    github.com/leaanthony/clir/command.go:172:      isHidden                100.0%
    github.com/leaanthony/clir/command.go:177:      Hidden                  100.0%
    github.com/leaanthony/clir/command.go:182:      NewSubCommand           100.0%
    github.com/leaanthony/clir/command.go:189:      AddCommand              100.0%
    github.com/leaanthony/clir/command.go:201:      BoolFlag                100.0%
    github.com/leaanthony/clir/command.go:208:      StringFlag              100.0%
    github.com/leaanthony/clir/command.go:215:      IntFlag                 100.0%
    github.com/leaanthony/clir/command.go:222:      LongDescription         100.0%
    total:                                          (statements)            97.6%
    
  • Bash Completion support

    Bash Completion support

    Would be really nice. I recently started working on a wails project, which uses this library for its cli. It would be nice to have clir automatically generate a bash completion script. From my quick glance at the source, a modified copy of the PrintHelp function could do the job.

  • Feature: Add Required and Shortcut

    Feature: Add Required and Shortcut

    This is obviously a large change, but add Shortcuts and Required commands that allow the user to set shortcut commands/flags and to mark a command/flag as required.

    CommandRequired() FlagRequired(flagName string) CommandShortCut(cmdShortCut string) FlagShortCut(flagLongName string, flagShortCut string)

    A bunch of examples are in the folder (required, shortcut, and advanced). The advanced example just ties a lot of things together showing some advanced usage. I've run a lot of commands through the code and after a few tweaks I think everything is working as expected. Haven't really done testing in golang before but can look at adding some test statements.

    To the "main loop" I've added code to convert command and flag shortcuts (runs over ALL args as a precaution for both flags and commands, but perhaps just need to test args[0] for commands)

    I then added a function call in the main loop called checkRequired, this checks all of the args to see what flags/commands were specified vs what commands/flags are required. It then prints out the error(s) for missing flags/commands.

    No external libraries were added, but "text/tabwriter" was added to format my portion of the help output.

  • Flags not parsed when additional args are provided

    Flags not parsed when additional args are provided

    Example:

    package main
    
    import (
    	"fmt"
    	"github.com/leaanthony/clir"
    )
    
    func main() {
    	cli := clir.NewCli("test", "Test", "v0.0.0")
    	s := cli.NewSubCommand("sub", "Desc")
    	var f string
    	s.StringFlag("f", "De", &f)
    	s.Action(func() error {
    		fmt.Println(f)
    		return nil
    	})
    	cli.Run()
    }
    

    Command

    go run main.go sub file -help
    

    Expected output

    test v0.0.0 - Test
    
    test sub - Desc
    Flags:
    
      -f string
            De
      -help
            Get help on the 'test sub' command.
    

    Actual output

    
    

    Update

    It seems that if the additional argument is provided after the flags it just works fine. However I don't consider this a viable solution. Now I can see some parallels to #9.


    I am going to address this in a PR.

  • Passing arguments

    Passing arguments

    Is it possible to pass arguments to the cli? E.g. I have a command like cli create test and I'd like the create cmd know that it has to create something named e.g. test.

  • A use-case clarification needed

    A use-case clarification needed

    Hi guys,

    We are currently evaluating a CLI utility to use with goxygen (a generator of web projects). I like the idea of a light-weight CLI utility that is straight forward and doesn't bring unneeded dependencies. That's why I thought we could try Clir. But I went through the Clirs documentation/examples and I can't figure out if it is capable of covering our use-case.

    Soon we'll have to implement something like this: goxygen init --frontend angular --db mysql my-new-app or goxygen init --frontend=angular --db=mysql my-new-app

    The options for the flags would have to be validated against a predefined set of parameters. Say for the --frontend flag the options could only be angular,react and vue, etc.

    Q: Can you please tell me if we can achieve this with Clir? Or how much of it can already be handled by the lib?

    Thank you.

    Best regards, Sasha.

Related tags
Dependency-Free Bencode Editor

rbEdit A statically compiled and dependency-free Bencode editor in Go, useful for command line use and scripts. Quick Start # Compile for linux arch:

Dec 28, 2022
Just a simple CLI tool to group dependabot PRs by dependency and merge them.
Just a simple CLI tool to group dependabot PRs by dependency and merge them.

Dependabotbot Have you been the victim of a lodash update? Has your notification page in Github been assaulted by needing to update a patch version of

Jun 30, 2022
word2text - a tool is to convert word documents (DocX) to text on the CLI with zero dependencies for free
word2text - a tool is to convert word documents (DocX) to text on the CLI with zero dependencies for free

This tool is to convert word documents (DocX) to text on the CLI with zero dependencies for free. This tool has been tested on: - Linux 32bit and 64 bit - Windows 32 bit and 64 bit - OpenBSD 64 bit

Apr 19, 2021
a Go language free and open-source document for learning from zero level

Go document a GO language free and open-source document for learning from zero level Please publish and collaborate OPEN-SOURCE Sections About go lang

Jan 8, 2023
Syno-cli - Synology unofficial API CLI and library

Synology CLI Unofficial wrapper over Synology API in Go. Focus on administrative

Jan 6, 2023
A few serve, the rest enjoy the free drinks

Tavern A few serve, the rest enjoy the free drinks. ⚠️ Work in progress, experimental As the Tavern client downloads, decrypts and publishes to the wo

Jul 29, 2022
depstat is a dependency analyzer for Go modules enabled projects.
depstat is a dependency analyzer for Go modules enabled projects.

depstat is a dependency analyzer for Go modules enabled projects. It runs as part of the Kubernetes CI pipeline to help evaluate dependency updates to Kubernetes.

Nov 1, 2022
CLI to run a docker image with R. CLI built using cobra library in go.
CLI  to run a docker image with R. CLI built using cobra library in go.

BlueBeak Installation Guide Task 1: Building the CLI The directory structure looks like Fastest process: 1)cd into bbtools 2)cd into bbtools/bin 3)I h

Dec 20, 2021
News-parser-cli - Simple CLI which allows you to receive news depending on the parameters passed to it
News-parser-cli - Simple CLI which allows you to receive news depending on the parameters passed to it

news-parser-cli Simple CLI which allows you to receive news depending on the par

Jan 4, 2022
Go-file-downloader-ftctl - A file downloader cli built using golang. Makes use of cobra for building the cli and go concurrent feature to download files.

ftctl This is a file downloader cli written in Golang which uses the concurrent feature of go to download files. The cli is built using cobra. How to

Jan 2, 2022
Go-api-cli - Small CLI to fetch data from an API sync and async

Async API Cli CLI to fetch data on "todos" from a given API in a number of ways.

Jan 13, 2022
Nebula Diagnosis CLI Tool is an information diagnosis cli tool for the nebula service and the node to which the service belongs.

Nebula Diagnosis CLI Tool is an information diagnosis cli tool for the nebula service and the node to which the service belongs.

Jan 12, 2022
A simple library to build golang command line (cli / cmd)apps

A simple library to build golang command line (cli / cmd)apps

Jan 11, 2022
Elegant CLI wrapper for kubeseal CLI

Overview This is a wrapper CLI ofkubeseal CLI, specifically the raw mode. If you just need to encrypt your secret on RAW mode, this CLI will be the ea

Jan 8, 2022
A wrapper of aliyun-cli subcommand alidns, run aliyun-cli in Declarative mode.

aliyun-dns A wrapper of aliyun-cli subcommand alidns, run aliyun-cli in Declarative mode. Installation Install aliyun-cli. Usage $ aliyun-dns -h A wra

Dec 21, 2021
Symfony-cli - The Symfony CLI tool For Golang

Symfony CLI Install To install Symfony CLI, please download the appropriate vers

Dec 28, 2022
Cli-algorithm - A cli program with A&DS in go!

cli-algorithm Objectives The objective of this cli is to implement 4 basic algorithms to sort arrays been Merge Sort Insertion Sort Bubble Sort Quick

Jan 2, 2022
Nebulant-cli - Nebulant's CLI
Nebulant-cli - Nebulant's CLI

Nebulant CLI Website: https://nebulant.io Documentation: https://nebulant.io/docs.html The Nebulant CLI tool is a single binary that can be used as a

Jan 11, 2022