109 lines
3.1 KiB
Nim
109 lines
3.1 KiB
Nim
# Implements a command line interface against the backend.
|
|
|
|
import backend, parseopt, strutils
|
|
|
|
const
|
|
USAGE = """nimcalculator - Nim cross platform calculator
|
|
(beta version, only integer addition is supported!)
|
|
|
|
Usage:
|
|
nimcalculator [options] [-a=value -b=value]
|
|
Options:
|
|
-a=value sets the integer value of the a parameter
|
|
-b=value sets the integer value of the b parameter
|
|
-h, --help shows this help
|
|
|
|
If no options are used, an interactive mode is entered.
|
|
"""
|
|
|
|
type
|
|
TCommand = enum # The possible types of operation
|
|
cmdParams, # Two valid parameters were provided
|
|
cmdInteractive # No parameters were provided, run interactive mode
|
|
|
|
TParamConfig = object of RootObj
|
|
action: TCommand # store the type of operation
|
|
paramA, paramB: int # possibly store the valid parameters
|
|
|
|
|
|
proc parseCmdLine(): TParamConfig =
|
|
## Parses the commandline.
|
|
##
|
|
## Returns a TParamConfig structure filled with the proper values or directly
|
|
## calls quit() with the appropriate error message.
|
|
var
|
|
hasA = false
|
|
hasB = false
|
|
p = initOptParser()
|
|
key, val: TaintedString
|
|
|
|
result.action = cmdInteractive # By default presume interactive mode.
|
|
try:
|
|
while true:
|
|
next p
|
|
key = p.key
|
|
val = p.val
|
|
|
|
case p.kind
|
|
of cmdArgument:
|
|
stdout.write USAGE
|
|
quit "Erroneous argument detected: " & key, 1
|
|
of cmdLongOption, cmdShortOption:
|
|
case key.normalize
|
|
of "help", "h":
|
|
stdout.write USAGE
|
|
quit 0
|
|
of "a":
|
|
result.paramA = val.parseInt
|
|
hasA = true
|
|
of "b":
|
|
result.paramB = val.parseInt
|
|
hasB = true
|
|
else:
|
|
stdout.write USAGE
|
|
quit "Unexpected option: " & key, 2
|
|
of cmdEnd: break
|
|
except ValueError:
|
|
stdout.write USAGE
|
|
quit "Invalid value " & val & " for parameter " & key, 3
|
|
|
|
if hasA and hasB:
|
|
result.action = cmdParams
|
|
elif hasA or hasB:
|
|
stdout.write USAGE
|
|
quit "Error: provide both A and B to operate in param mode", 4
|
|
|
|
|
|
proc parseUserInput(question: string): int =
|
|
## Parses a line of user input, showing question to the user first.
|
|
##
|
|
## If the user input is an empty line quit() is called. Returns the value
|
|
## parsed as an integer.
|
|
while true:
|
|
echo question
|
|
let input = stdin.readLine
|
|
try:
|
|
result = input.parseInt
|
|
break
|
|
except ValueError:
|
|
if input.len < 1: quit "Blank line detected, quitting.", 0
|
|
echo "Sorry, `$1' doesn't seem to be a valid integer" % input
|
|
|
|
proc interactiveMode() =
|
|
## Asks the user for two integer values, adds them and exits.
|
|
let
|
|
paramA = parseUserInput("Enter the first parameter (blank to exit):")
|
|
paramB = parseUserInput("Enter the second parameter (blank to exit):")
|
|
echo "Calculating... $1 + $2 = $3" % [$paramA, $paramB,
|
|
$backend.myAdd(paramA, paramB)]
|
|
|
|
|
|
when isMainModule:
|
|
## Main entry point.
|
|
let opt = parseCmdLine()
|
|
if cmdParams == opt.action:
|
|
echo "Param mode: $1 + $2 = $3" % [$opt.paramA, $opt.paramB,
|
|
$backend.myAdd(opt.paramA, opt.paramB)]
|
|
else:
|
|
echo "Entering interactive addition mode"
|
|
interactiveMode()
|