A simple python library to build command-line interfaces. Heavily inspired by Cobra.
pip install pikli
Pikli is a command line parser. It parses the arguments provided on the command prompt & decides whether its a command or a flag or an argument for a command & acts accordingly. A command may have: Flags , Arguments & Sub Commands. In the following example:
#main.py
import pikli
def start_server(arg):
print("HTTP server running")
root = pikli.Command(use = "hello" , short = "hello is a cli app")
serve = pikli.Command(use = "serve" , short = "starts the http server",
run = start_server
)
root.add_command(serve)
root.execute()
We have two commands root
& serve
. root
as its name suggests is the root command. This decision is made by providing a parent-child relationship. Its basically a tree like structure. And the command which sits at the top of the tree is the root. The serve
command is made a sub/child command of root
by the add_command
method of the Command
class.The add_command
method takes arbitrary amount of commands to add as a sub command
. And execute
does exactly what it looks like, executes the command. Now onto the parameters provided while creating the objects:
use
: Determines the name of the command. Mandatory.
short
: A short description of the command.
long
: A long description of the command.
run
: The function which is triggered when the execute
method of a command is called. There is a thing to remember about the run
funtion. The function which is to be used as the run
function(in this case start_server), must have a single parameter which will be used as a list..
Flags are extra options used with a command. For example: git commit -m "Initial Commit"
here, git is the root command, commit is the sub command, -m is the flag
& the string after that is its value. Now lets see a pikli example:
import pikli
def start_server(arg):
print("HTTP server running on port: {}".format(pikli.get_int("port")))
root = pikli.Command(use = "hello" , short = "hello is a cli app")
serve = pikli.Command(use = "serve" , short = "starts the http server",
run = start_server
)
serve.flags().intp("port" , "p" , 8000 , "the port on which the server runs")
root.add_command(serve)
root.execute()
The flags
method of a Command
returns the flag
object that handles every flag related activity for the command. intp
is a method of that object which creates an integer flag
.There is also stringp
& boolp
. The first parameter is the name of the flag(used in the long version), the second one is the usable name of the flag like, -p
. The third parameter is the default value for the flag. There is no default value for the bool flag. Its False by default. And the fourth one should be obvious, a description of the flag. Now lets use everything we have seen so far:
python main.py serve -p 8080
or
python main.py serve --port=8080
The output should be:
HTTP server running on port: 8080
Executing the serve command without the p
flag will return the default value when pikli.get_int("port")
is called which is a pikli core function used for retrieving the value of an integer flag. Similarly there are get_str
& get_bool
to get string & bool flag values.
Pikli provides an automatic help flag generation & recognition. Whenever a command
without a run
function is executed, the help
flag will be executed autmatically. Or, it can be explicitly mentioned like any other flag like -h
or --help
. Try:
python main.py serve --help
Simply running python main.py
will trigger its help flag as it has no run
function. A help flag should display something similar:
hello is a cli app
Usage:
hello [args] [flags] [sub commands]
Available Commands:
serve starts the http server
Flags:
-h, --help Shows info regarding the command
Pikli provides support for persistent flags
. Persistent flags
are like normal flags
except if you assign it to a command
it automatically gets assigned to every child it has upto the bottom of the command
tree. So if a persistent flag
is assigned to the root command
then every command
will get that flag
.
import pikli
def start_server(arg):
if pikli.get_bool("verbose"):
print("showing details")
print("HTTP server running on port: {}".format(pikli.get_int("port")))
root = pikli.Command(use = "hello" , short = "hello is a cli app")
serve = pikli.Command(use = "serve" , short = "starts the http server",
run = start_server
)
serve.flags().intp("port" , "p" , 8000 , "the port on which the server runs")
root.add_command(serve)
root.persistent_flags().boolp("verbose" , "v" , "shows details regarding the operation")
root.execute()
Here the verbose flag
is assigned to the root command
making this flag a global one. When assigning persistent flags
, don't forget to add all the sub commands
at first.
Apart from sub commands
& flags
normal arguments can be used in pikli. All that is needed is the arg
list that is used as the parameter of the run
function. Lets see an example:
import pikli
def greet(arg):
print("Hello {}, beef cheese delight rocks".format(arg[0]))
root = pikli.Command(use = "hello" , short = "hello is a greeting app",
run = greet)
root.persistent_flags().boolp("verbose" , "v" , "shows details regarding the operation")
root.execute()
Just keep the index order of the arguments
right. The index number of the arguments
doesn't bother about the flags
. For example python main.py -v "John Doe"
pikli will ignore the flags & count the argument
John Doe as index 0 & so on. The output should be:
Hello John Doe, beef cheese delight rocks
Lastly you can get the string or integer environmental variables using pikli. The two functions for this are get_str_env
& get_int_env
:
import pikli
def greet(arg):
print("Hello {}, beef cheese delight rocks".format(pikli.get_str_env("NAME")))
root = pikli.Command(use = "hello" , short = "hello is a greeting app",
run = greet)
root.execute()
Run it like this:
NAME="John Doe" python main.py
Totally open to suggestions. See the contribution guide
Pikli is licensed under the MIT License