The first thing I notice with your code is that the code is a very long global script. To resolve this I'd start by moving your code into functions.
The actual calculations could be as simple as say:
def add(arg1, arg2):
print(float(arg1) + float(arg2))
To then get the help information we could add a docstring.
def add(arg1, arg2):
"""
Add:
Description: Adds 2 numbers
Syntax: add [num1] [num2]
"""
print(float(arg1) + float(arg2))
We can get both the docstring and the output of the operation with Python. To get the docstring to be nicely formatted we can use textwrap.dedent.
>>> add("10", "5")
15.0
>>> import textwrap
>>> textwrap.dedent(add.__doc__.strip("\n"))
Add:
Description: Adds 2 numbers
Syntax: add [num1] [num2]
To then reduce the amount of lines of code we can bundle all these functions into a dictionary. And just index the dictionary to get a specific function.
COMMANDS = {
"add": add,
"sub": sub,
# ...
}
fn = COMMANDS["add"]
fn("10", "5")
15.0
Whilst you can build the dictionary and execute the commands yourself, you could instead subclass cmd.Cmd. You will need to change the functions slightly to only take a string as input, and prefix do_ to any commands available to the commandline.
import cmd
class PyCMD(cmd.Cmd):
intro = 'Welcome to pyCMD, user\nStarting command line, use "help" for help'
prompt = ": "
def do_add(self, arg):
"""
Add:
Description: Adds 2 numbers
Syntax: add [num1] [num2]
"""
arg1, arg2 = arg.split()
print(float(arg1) + float(arg2))
PyCMD().cmdloop()
Welcome to pyCMD, user
Starting command line, use "help" for help
: help
Documented commands (type help <topic>):
========================================
add help
: help add
Add:
Description: Adds 2 numbers
Syntax: add [num1] [num2]
: add 10 5
15.0
The help is clearly a bit on the broken side. To fix this we can change the docstring after the function.
class PyCMD(cmd.Cmd):
def do_add(self, arg):
# ...
do_add.__doc__ = textwrap.dedent(do_add.__doc__.rstrip(" ").strip("\n"))
This is a bit ugly and doing this for each function would be horrible. So we can create a function to do this.
def clean_doc(fn):
fn.__doc__ = textwrap.dedent(fn.__doc__.rstrip(" ").strip("\n"))
class PyCMD(cmd.Cmd):
def do_add(self, arg):
# ...
clean_doc(do_add)
This is still a bit on the ugly side so we can use @ to do this for us. This is called a decorator. This makes sense because we're decorating how __doc__ is seen. Note that we changed clean_doc to return fn.
def clean_doc(fn):
fn.__doc__ = textwrap.dedent(fn.__doc__.rstrip(" ").strip("\n"))
return fn
class PyCMD(cmd.Cmd):
@clean_doc
def do_add(self, arg):
# ...
We can add another function like clean_doc, but this time make it a closure if you want to easily add your validation of two arguments.
import functools
def command(fn):
@functools.wraps(fn)
def wrapper(self, arg):
args = [token for token in arg.split()]
try:
arg1, arg2 = args
except ValueError:
print('Too many or too little args, 2 args required, if you want to not use an arg, use a "."')
else:
return fn(self, arg1, arg2)
return wrapper
class PyCMD(cmd.Cmd):
@command
@clean_doc
def do_add(self, arg1, arg2):
"""
Add:
Description: Adds 2 numbers
Syntax: add [num1] [num2]
"""
print(float(arg1) + float(arg2))
import cmd
import textwrap
import functools
def command(fn):
@functools.wraps(fn)
def wrapper(self, arg):
try:
arg1, arg2 = arg.split()
except ValueError:
print('Too many or too little args, 2 args required, if you want to not use an arg, use a "."')
else:
return fn(self, arg1, arg2)
return wrapper
def clean_doc(fn):
fn.__doc__ = textwrap.dedent(fn.__doc__.rstrip(" ").strip("\n"))
return fn
class PyCMD(cmd.Cmd):
intro = 'Welcome to pyCMD, user\nStarting command line, use "help" for help'
prompt = ": "
@command
@clean_doc
def do_add(self, arg1, arg2):
"""
Add:
Description: Adds 2 numbers
Syntax: add [num1] [num2]
"""
print(float(arg1) + float(arg2))
PyCMD().cmdloop()
Welcome to pyCMD, user
Starting command line, use "help" for help
: help
Documented commands (type help <topic>):
========================================
add help
: help add
Add:
Description: Adds 2 numbers
Syntax: add [num1] [num2]
: add 10 5
15.0
Other command left for you to implement