# -*- coding: utf-8 -*-
"""CLI handler for canvas program based on a custom argparser."""
# Standard library imports
import argparse
import sys
# Local imports
from canvascli.canvas import Canvas
from canvascli.utils import positive_int
# PY2/PY3 compatibility. We could use `six` if more things are needed.
if sys.version_info[0] == 2: # pragma: no cover
input = raw_input # noqa
[docs]class ArgumentParserError(Exception):
"""Custom exception for ThrowingArgumentParser."""
def __init__(self, message):
super(ArgumentParserError, self).__init__()
self.message = message
[docs]class ThrowingArgumentParser(argparse.ArgumentParser):
"""Custom argument parser that avoids exit on errors."""
[docs] def error(self, message):
"""Override method to prevent SystemExit and raise custom exception."""
raise ArgumentParserError(message=message)
[docs]class CommandParserHandler(object):
"""CLI handler for canvas program based on argparse."""
HELP = "Type 'H' for help"
def __init__(self):
"""CLI handler for canvas program based on argparse."""
self._canvas = Canvas()
self._parser = self.create_parser()
self._command_history = []
# --- Helper methods
# -------------------------------------------------------------------------
[docs] def create_parser(self):
"""Create the custom parser to evaluate canvas CLI commands."""
parser = ThrowingArgumentParser(
description='CanvasCLI: the simple console version of a drawing '
'program!',
add_help=False,
)
subparsers = parser.add_subparsers(help='Program commands')
# Help command
help_parser = subparsers.add_parser('H', add_help=False)
help_parser.set_defaults(func=self.print_help)
help_parser.set_defaults(help='Display help')
# Create command
create_parser = subparsers.add_parser('C', add_help=False)
create_parser.add_argument('width', type=positive_int,
help='Canvas width')
create_parser.add_argument('height', type=positive_int,
help='Canvas height')
create_parser.set_defaults(func=self.create_canvas)
create_parser.set_defaults(help='Create a new canvas of given size')
# Line command
draw_line_parser = subparsers.add_parser('L', add_help=False)
draw_line_parser.add_argument('x1', type=positive_int,
help='Point 1 x coordinate')
draw_line_parser.add_argument('y1', type=positive_int,
help='Point 1 y coordinate')
draw_line_parser.add_argument('x2', type=positive_int,
help='Point 2 x coordinate')
draw_line_parser.add_argument('y2', type=positive_int,
help='Point 2 y coordinate')
draw_line_parser.set_defaults(func=self._canvas.draw_line)
draw_line_parser.set_defaults(help='Draw a Line from (x1,y1) to '
'(x2,y2)')
# Rectangle command
draw_rectangle_parser = subparsers.add_parser('R', add_help=False)
draw_rectangle_parser.add_argument('x1', type=positive_int,
help='Upper left corner x '
'coordinate')
draw_rectangle_parser.add_argument('y1', type=positive_int,
help='Upper left corner y '
'coordinate')
draw_rectangle_parser.add_argument('x2', type=positive_int,
help='Lower right corner x '
'coordinate')
draw_rectangle_parser.add_argument('y2', type=positive_int,
help='Lower right corner y '
'coordinate')
draw_rectangle_parser.set_defaults(func=self._canvas.draw_rectangle)
draw_rectangle_parser.set_defaults(help='Draw a Rectangle given by '
'(x1,y1) and (x2,y2)')
# Fill command
fill_parser = subparsers.add_parser('B', add_help=False)
fill_parser.add_argument('x', type=positive_int,
help='Point x coordinate')
fill_parser.add_argument('y', type=positive_int,
help='Point y coordinate')
fill_parser.add_argument('color', type=str, help='Expressed as '
'an ASCII single character')
fill_parser.set_defaults(func=self._canvas.fill)
fill_parser.set_defaults(help='Fill the area connected to (x,y) with '
'color')
# Erase command
fill_parser = subparsers.add_parser('E', add_help=False)
fill_parser.set_defaults(func=self._canvas.erase)
fill_parser.set_defaults(help="Erase the contents of the canvas.")
# Quit command
quit_parser = subparsers.add_parser('Q', add_help=False)
quit_parser.set_defaults(func=sys.exit)
quit_parser.set_defaults(help='Quit program')
return parser
[docs] def parse_args(self, args):
"""Convenience method for calling the argument parser."""
self._command_history.append(args)
return self._parser.parse_args(args)
[docs] def print_help(self, args=None):
"""Print help for the cli canvas program."""
args = args
print(self.format_help())
# --- Canvas methods requiring special handling
# -------------------------------------------------------------------------
[docs] def create_canvas(self, width, height):
"""Create a new canvas of given size."""
if self._canvas.data is None:
self._canvas.create(width, height)
else:
while True:
answer = input('This will replace the previous '
'canvas! Want to proceed? [Y/N]: ')
answer = answer .strip().lower()
if answer in ['y', 'yes']:
self._canvas.create(width, height)
break
elif answer in ['n', 'no']:
break
[docs] def print_canvas(self):
"""Convenience method for printing the Canvas."""
if self._canvas._canvas:
print(self._canvas)