mirror of https://github.com/sgoudham/Enso-Bot.git
parent
42348e0ae2
commit
9439532533
@ -1,3 +0,0 @@
|
|||||||
UNKNOWN
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
pip
|
|
@ -1,15 +0,0 @@
|
|||||||
Metadata-Version: 2.0
|
|
||||||
Name: Menus
|
|
||||||
Version: 0.2.0
|
|
||||||
Summary: Create cli menus with ease
|
|
||||||
Home-page: https://github.com/JMSwag/Menus
|
|
||||||
Author: Digital Sapphire
|
|
||||||
Author-email: menus@digitalsapphire.io
|
|
||||||
License: MIT
|
|
||||||
Platform: UNKNOWN
|
|
||||||
Requires-Dist: dsdev-utils
|
|
||||||
Requires-Dist: six
|
|
||||||
|
|
||||||
UNKNOWN
|
|
||||||
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
|||||||
Menus-0.2.0.dist-info/DESCRIPTION.rst,sha256=OCTuuN6LcWulhHS3d5rfjdsQtW22n7HENFRh6jC6ego,10
|
|
||||||
Menus-0.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
|
||||||
Menus-0.2.0.dist-info/METADATA,sha256=5E660I04WM6yX5M3KfFsqJZNz5l4kckz3MFAou_1Iu0,280
|
|
||||||
Menus-0.2.0.dist-info/RECORD,,
|
|
||||||
Menus-0.2.0.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110
|
|
||||||
Menus-0.2.0.dist-info/metadata.json,sha256=k5fJgBoAIoSIFjuR1yUm6YALlY9n5FTybcF8RqhDLjQ,480
|
|
||||||
Menus-0.2.0.dist-info/top_level.txt,sha256=mr-Mm53IP5nmAdXmK0MURdgtX5aoNBmIrgHgyPdKUac,11
|
|
||||||
Menus-0.2.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
||||||
menus/__init__.py,sha256=Racmika2iOJjIGPzbSZs8hQARcJaif_N2rLyz0uUGJY,1419
|
|
||||||
menus/__pycache__/__init__.cpython-36.pyc,,
|
|
||||||
menus/__pycache__/_version.cpython-36.pyc,,
|
|
||||||
menus/__pycache__/engine.cpython-36.pyc,,
|
|
||||||
menus/__pycache__/example.cpython-36.pyc,,
|
|
||||||
menus/__pycache__/exceptions.cpython-36.pyc,,
|
|
||||||
menus/__pycache__/menu.cpython-36.pyc,,
|
|
||||||
menus/__pycache__/utils.cpython-36.pyc,,
|
|
||||||
menus/_version.py,sha256=Z0DxOc2U4ydSV42gG9XZ6DRszh-5f53SRi3SAzpPxKU,471
|
|
||||||
menus/engine.py,sha256=tG6395XNJ4LcKzE76hdcDGGrOFPRYrOXdV6pjIN9Rb0,3315
|
|
||||||
menus/example.py,sha256=tLYJJTtloPBfFc3kui6s-d_nPAXyEdGs8gqjssHOIpA,3292
|
|
||||||
menus/exceptions.py,sha256=Widb24ezSJNpMy8Dt8Wi_xQmXA561x3cI4hj27Br2_4,2400
|
|
||||||
menus/menu.py,sha256=kMzIcnwPsFHQLEN2NKQ0m4EUqTlzBKNlVnje7tJ6Cbs,6983
|
|
||||||
menus/utils.py,sha256=ReoV8xbA9SjX6psiSPevG-A7NVJWQLmz0rVw7MLuPIQ,3670
|
|
||||||
site/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
||||||
site/__pycache__/__init__.cpython-36.pyc,,
|
|
@ -1,6 +0,0 @@
|
|||||||
Wheel-Version: 1.0
|
|
||||||
Generator: bdist_wheel (0.29.0)
|
|
||||||
Root-Is-Purelib: true
|
|
||||||
Tag: py2-none-any
|
|
||||||
Tag: py3-none-any
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
{"extensions": {"python.details": {"contacts": [{"email": "menus@digitalsapphire.io", "name": "Digital Sapphire", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/JMSwag/Menus"}}}, "extras": [], "generator": "bdist_wheel (0.29.0)", "license": "MIT", "metadata_version": "2.0", "name": "Menus", "run_requires": [{"requires": ["dsdev-utils", "six"]}], "summary": "Create cli menus with ease", "version": "0.2.0"}
|
|
@ -1,2 +0,0 @@
|
|||||||
menus
|
|
||||||
site
|
|
@ -1,37 +0,0 @@
|
|||||||
# The MIT License (MIT)
|
|
||||||
#
|
|
||||||
# Copyright (c) 2016 Digital Sapphire
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
|
||||||
# in the Software without restriction, including without limitation the rights
|
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included in
|
|
||||||
# all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from menus.engine import Engine
|
|
||||||
from menus.exceptions import MenusError
|
|
||||||
from menus.menu import BaseMenu
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['BaseMenu', 'Engine', 'MenusError']
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger()
|
|
||||||
|
|
||||||
|
|
||||||
from ._version import get_versions # noqa
|
|
||||||
__version__ = get_versions()['version']
|
|
||||||
del get_versions
|
|
@ -1,21 +0,0 @@
|
|||||||
|
|
||||||
# This file was generated by 'versioneer.py' (0.15) from
|
|
||||||
# revision-control system data, or from the parent directory name of an
|
|
||||||
# unpacked source archive. Distribution tarballs contain a pre-generated copy
|
|
||||||
# of this file.
|
|
||||||
|
|
||||||
import json
|
|
||||||
import sys
|
|
||||||
|
|
||||||
version_json = '''
|
|
||||||
{
|
|
||||||
"dirty": false,
|
|
||||||
"error": null,
|
|
||||||
"full-revisionid": "4dd50cb49a508b57d56a4d512ef40da67b01ab77",
|
|
||||||
"version": "0.2.0"
|
|
||||||
}
|
|
||||||
''' # END VERSION_JSON
|
|
||||||
|
|
||||||
|
|
||||||
def get_versions():
|
|
||||||
return json.loads(version_json)
|
|
@ -1,96 +0,0 @@
|
|||||||
# --------------------------------------------------------------------------
|
|
||||||
# Copyright (c) 2016 Digital Sapphire
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files
|
|
||||||
# (the "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
# persons to whom the Software is furnished to do so, subject to the
|
|
||||||
# following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be
|
|
||||||
# included in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
||||||
# ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
||||||
# TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
||||||
# SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
|
||||||
# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
||||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
|
||||||
# OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
import logging
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from menus.example import load_example_menus
|
|
||||||
from menus.exceptions import MenusError
|
|
||||||
from menus.menu import BaseMenu, MainMenu
|
|
||||||
from menus.utils import check_commands_else_raise
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
# Ensure that a custom menus subclasses BaseMenu
|
|
||||||
def check_mro(c):
|
|
||||||
if issubclass(c.__class__, BaseMenu) is False:
|
|
||||||
raise MenusError('Not a sublcass of BaseMenu \n\nclass '
|
|
||||||
'{}'.format(c.__class__.__name__),
|
|
||||||
expected=True)
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
class Engine(object):
|
|
||||||
|
|
||||||
def __init__(self, app_name=None, menus=None, example=False):
|
|
||||||
# Name used in every menu header
|
|
||||||
if app_name is None:
|
|
||||||
app_name = 'ACME'
|
|
||||||
|
|
||||||
# Create initial commands for main menu
|
|
||||||
sub_menus = []
|
|
||||||
|
|
||||||
# Adding submenus
|
|
||||||
if example is True:
|
|
||||||
sub_menus += load_example_menus()
|
|
||||||
else:
|
|
||||||
if menus is not None:
|
|
||||||
for m in menus:
|
|
||||||
check_mro(m)
|
|
||||||
sub_menus += menus
|
|
||||||
|
|
||||||
# Commands with app_name added to it
|
|
||||||
new_sub_menus = []
|
|
||||||
for sub in sub_menus:
|
|
||||||
# Adding the app name to the menu
|
|
||||||
sub.app_name = app_name
|
|
||||||
sub.commands.append(('Main Menu', getattr(sub, 'done')))
|
|
||||||
|
|
||||||
# Quick hack to add users class name as menu option
|
|
||||||
# only for main menu
|
|
||||||
new_sub_menu = (sub.menu_name, sub)
|
|
||||||
new_sub_menus.append(new_sub_menu)
|
|
||||||
|
|
||||||
new_sub_menus.append(('Quit', self.quit))
|
|
||||||
|
|
||||||
# Sanatisation checks on passed commands
|
|
||||||
check_commands_else_raise(new_sub_menus)
|
|
||||||
|
|
||||||
# Initilazie main menu with submenus
|
|
||||||
self.main = MainMenu(new_sub_menus)
|
|
||||||
|
|
||||||
# Adding the app name to the main menu
|
|
||||||
self.main.app_name = app_name
|
|
||||||
|
|
||||||
# Starts event loop
|
|
||||||
def start(self): # pragma: no cover
|
|
||||||
while 1:
|
|
||||||
start = self.main.display()
|
|
||||||
start()
|
|
||||||
|
|
||||||
def quit(self): # pragma: no cover
|
|
||||||
log.debug('Quitting')
|
|
||||||
sys.exit(0)
|
|
@ -1,98 +0,0 @@
|
|||||||
# --------------------------------------------------------------------------
|
|
||||||
# Copyright (c) 2016 Digital Sapphire
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files
|
|
||||||
# (the "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
# persons to whom the Software is furnished to do so, subject to the
|
|
||||||
# following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be
|
|
||||||
# included in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
||||||
# ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
||||||
# TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
||||||
# SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
|
||||||
# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
||||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
|
||||||
# OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from menus.menu import BaseMenu
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class Cool(BaseMenu):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
# An option is a tuple which consists of ('Display Name', function)
|
|
||||||
commands = [('Speak', self.speak)]
|
|
||||||
super(Cool, self).__init__(commands=commands)
|
|
||||||
|
|
||||||
def speak(self):
|
|
||||||
# Used to nicely display a message towards
|
|
||||||
# the middle of the screen
|
|
||||||
self.display_msg('Cool is speaking')
|
|
||||||
|
|
||||||
# Will pause for 3 seconds
|
|
||||||
self.pause(seconds=3)
|
|
||||||
|
|
||||||
# Used to return to Cool Menu. If omitted
|
|
||||||
# the user will be returned to the Main Menu
|
|
||||||
self()
|
|
||||||
|
|
||||||
|
|
||||||
class Hot(BaseMenu):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
# An option is a tuple which consists of ('Display Name', function)
|
|
||||||
commands = [('Speak', self.speak)]
|
|
||||||
super(Hot, self).__init__(commands=commands, menu_name='Really Hot')
|
|
||||||
|
|
||||||
def speak(self):
|
|
||||||
# Used to nicely display a message towards
|
|
||||||
# the middle of the screen
|
|
||||||
self.display_msg("It's getting hot in here!")
|
|
||||||
|
|
||||||
# Will pause for 3 seconds
|
|
||||||
self.pause(seconds=3)
|
|
||||||
|
|
||||||
# Used to return to Cool Menu. If omitted
|
|
||||||
# the user will be returned to the Main Menu
|
|
||||||
self()
|
|
||||||
|
|
||||||
|
|
||||||
class Keys(BaseMenu):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
# An option is a tuple which consists of ('Display Name', function)
|
|
||||||
commands = [('Show Public Key', self.show_public_key)]
|
|
||||||
|
|
||||||
super(Keys, self).__init__(commands=commands)
|
|
||||||
|
|
||||||
def show_public_key(self):
|
|
||||||
log.debug('Show public key')
|
|
||||||
|
|
||||||
# Used to nicely display a message towards
|
|
||||||
# the middle of the screen
|
|
||||||
self.display_msg('thdkalfjl;da;ksfkda;fdkj')
|
|
||||||
|
|
||||||
# Will prompt user to press enter to continue
|
|
||||||
self.pause(enter_to_continue=True)
|
|
||||||
|
|
||||||
# Used to return to Cool Menu. If omitted
|
|
||||||
# the user will be returned to the Main Menu
|
|
||||||
self()
|
|
||||||
|
|
||||||
|
|
||||||
# List of menus to be used when user initializes Engine(example=True)
|
|
||||||
def load_example_menus():
|
|
||||||
return [Cool(), Hot(), Keys()]
|
|
@ -1,69 +0,0 @@
|
|||||||
# --------------------------------------------------------------------------
|
|
||||||
# Copyright (c) 2016 Digital Sapphire
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files
|
|
||||||
# (the "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
# persons to whom the Software is furnished to do so, subject to the
|
|
||||||
# following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be
|
|
||||||
# included in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
||||||
# ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
||||||
# TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
||||||
# SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
|
||||||
# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
||||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
|
||||||
# OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
|
|
||||||
class STDError(Exception):
|
|
||||||
"""Extends exceptions to show added message if error isn't expected.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
|
|
||||||
msg (str): error message
|
|
||||||
|
|
||||||
Kwargs:
|
|
||||||
|
|
||||||
tb (obj): is the original traceback so that it can be printed.
|
|
||||||
|
|
||||||
expected (bool):
|
|
||||||
|
|
||||||
Meaning:
|
|
||||||
|
|
||||||
True - Report issue msg not shown
|
|
||||||
|
|
||||||
False - Report issue msg shown
|
|
||||||
"""
|
|
||||||
def __init__(self, msg, tb=None, expected=False):
|
|
||||||
if not expected:
|
|
||||||
msg = msg + ('; please report this issue on https://git'
|
|
||||||
'hub.com/JMSwag/Menus')
|
|
||||||
msg = '\n\n' + msg
|
|
||||||
super(STDError, self).__init__(msg)
|
|
||||||
|
|
||||||
self.traceback = tb
|
|
||||||
self.exc_info = sys.exc_info() # preserve original exception
|
|
||||||
|
|
||||||
def format_traceback(self):
|
|
||||||
if self.traceback is None:
|
|
||||||
return None
|
|
||||||
return ''.join(traceback.format_tb(self.traceback))
|
|
||||||
|
|
||||||
|
|
||||||
class MenusError(STDError):
|
|
||||||
"""Raised for Archiver exceptions"""
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(MenusError, self).__init__(*args, **kwargs)
|
|
@ -1,206 +0,0 @@
|
|||||||
# --------------------------------------------------------------------------
|
|
||||||
# Copyright (c) 2016 Digital Sapphire
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
# a copy of this software and associated documentation files
|
|
||||||
# (the "Software"), to deal in the Software without restriction, including
|
|
||||||
# without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
# distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
||||||
# persons to whom the Software is furnished to do so, subject to the
|
|
||||||
# following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be
|
|
||||||
# included in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
||||||
# ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
||||||
# TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
||||||
# SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
|
||||||
# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
||||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
|
||||||
# OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
# --------------------------------------------------------------------------
|
|
||||||
from __future__ import print_function
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
from dsdev_utils.terminal import (ask_yes_no,
|
|
||||||
get_correct_answer,
|
|
||||||
get_terminal_size)
|
|
||||||
import six
|
|
||||||
|
|
||||||
from menus.exceptions import MenusError
|
|
||||||
from menus.utils import clear_screen_cmd, Getch
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class BaseMenu(object):
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
# Used to display the apps name on all menu headers
|
|
||||||
self.app_name = None
|
|
||||||
|
|
||||||
# The custom menu name
|
|
||||||
self.menu_name = kwargs.get('menu_name')
|
|
||||||
|
|
||||||
# If we do not have a custom menu
|
|
||||||
# name then use the class name
|
|
||||||
if self.menu_name is None:
|
|
||||||
self.menu_name = self.__class__.__name__
|
|
||||||
|
|
||||||
# A message to display when this menus loads
|
|
||||||
self.message = kwargs.get('message')
|
|
||||||
|
|
||||||
# User commands for this menu
|
|
||||||
self._commands = kwargs.get('commands', [])
|
|
||||||
|
|
||||||
# ToDo: Remove in v1.0
|
|
||||||
# User commands for this menu
|
|
||||||
options = kwargs.get('options', [])
|
|
||||||
if len(options) > 0:
|
|
||||||
if len(self._commands) > 0:
|
|
||||||
raise MenusError('Cannot mix old & new API. Use '
|
|
||||||
'commands kwarg only.')
|
|
||||||
|
|
||||||
warn_msg = ('BaseMenu(options=[]) is deprecated, '
|
|
||||||
'user BaseMenu(commands=[]')
|
|
||||||
warnings.warn(warn_msg)
|
|
||||||
self._commands += options
|
|
||||||
# End ToDo
|
|
||||||
|
|
||||||
@property
|
|
||||||
def commands(self):
|
|
||||||
return self._commands
|
|
||||||
|
|
||||||
def __call__(self):
|
|
||||||
x = self.display()
|
|
||||||
x()
|
|
||||||
|
|
||||||
def display(self):
|
|
||||||
self._display_menu_header()
|
|
||||||
self.display_msg(self.message)
|
|
||||||
return self._menu_options(self._commands)
|
|
||||||
|
|
||||||
def pause(self, seconds=5, enter_to_continue=False):
|
|
||||||
if not isinstance(enter_to_continue, bool):
|
|
||||||
raise MenusError('enter_to_continue must be boolean',
|
|
||||||
expected=True)
|
|
||||||
if not isinstance(seconds, six.integer_types):
|
|
||||||
raise MenusError('seconds must be integer', expected=True)
|
|
||||||
|
|
||||||
if enter_to_continue is True:
|
|
||||||
self.display_msg('Press enter to quit')
|
|
||||||
six.moves.input()
|
|
||||||
else:
|
|
||||||
time.sleep(seconds)
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Prompt the user with a question & only accept
|
|
||||||
# yes or no answers
|
|
||||||
def ask_yes_no(self, question, default):
|
|
||||||
return ask_yes_no(question, default)
|
|
||||||
|
|
||||||
# Promot the user with a question & confirm it's correct.
|
|
||||||
# If required is True, user won't be able to enter a blank answer
|
|
||||||
def get_correct_answer(self, question, default, required=False):
|
|
||||||
return get_correct_answer(question, default, required)
|
|
||||||
|
|
||||||
# Display a message centered on the screen.
|
|
||||||
def display_msg(self, message=None):
|
|
||||||
self._display_msg(message)
|
|
||||||
|
|
||||||
def done(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
# ToDo: Remove in v1.0
|
|
||||||
def get_correct_action(self, question, default, required):
|
|
||||||
return get_correct_answer(question, default, required)
|
|
||||||
# End ToDo
|
|
||||||
|
|
||||||
# Takes a string and adds it to the menu header along side
|
|
||||||
# the app name.
|
|
||||||
def _display_menu_header(self):
|
|
||||||
window_size = get_terminal_size()[0]
|
|
||||||
|
|
||||||
# Adding some styling to the header
|
|
||||||
def add_style():
|
|
||||||
top = '*' * window_size + '\n'
|
|
||||||
bottom = '\n' + '*' * window_size + '\n'
|
|
||||||
|
|
||||||
header = self.app_name + ' - ' + self.menu_name
|
|
||||||
header = header.center(window_size)
|
|
||||||
msg = top + header + bottom
|
|
||||||
return msg
|
|
||||||
|
|
||||||
os.system(clear_screen_cmd)
|
|
||||||
print(add_style())
|
|
||||||
|
|
||||||
def _display_msg(self, message):
|
|
||||||
window_size = get_terminal_size()[0]
|
|
||||||
if message is None:
|
|
||||||
return ''
|
|
||||||
|
|
||||||
if not isinstance(message, six.string_types):
|
|
||||||
log.warning('Did not pass str')
|
|
||||||
return ''
|
|
||||||
|
|
||||||
# Home grown word wrap
|
|
||||||
def format_msg():
|
|
||||||
formatted = []
|
|
||||||
finished = ['\n']
|
|
||||||
count = 0
|
|
||||||
words = message.split(' ')
|
|
||||||
for w in words:
|
|
||||||
w = w + ' '
|
|
||||||
if count + len(w) > window_size / 2:
|
|
||||||
finished.append(''.join(formatted).center(window_size))
|
|
||||||
finished.append('\n')
|
|
||||||
count = len(w)
|
|
||||||
# Starting a new line.
|
|
||||||
formatted = []
|
|
||||||
formatted.append(w)
|
|
||||||
else:
|
|
||||||
formatted.append(w)
|
|
||||||
count += len(w)
|
|
||||||
finished.append(''.join(formatted).center(window_size))
|
|
||||||
finished.append('\n')
|
|
||||||
return ''.join(finished)
|
|
||||||
print(format_msg())
|
|
||||||
|
|
||||||
# Takes a list of tuples(menu_name, call_back) adds menu numbers
|
|
||||||
# then prints menu to screen.
|
|
||||||
# Gets input from user, then returns the callback
|
|
||||||
def _menu_options(self, commands=None):
|
|
||||||
|
|
||||||
def add_options():
|
|
||||||
getch = Getch()
|
|
||||||
menu = []
|
|
||||||
count = 1
|
|
||||||
for s in commands:
|
|
||||||
item = '{}. {}\n'.format(count, s[0])
|
|
||||||
menu.append(item)
|
|
||||||
count += 1
|
|
||||||
print(''.join(menu))
|
|
||||||
answers = []
|
|
||||||
for a in six.moves.range(1, len(menu) + 1):
|
|
||||||
answers.append(str(a))
|
|
||||||
while 1:
|
|
||||||
ans = getch()
|
|
||||||
if ans in answers:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
log.debug('Not an acceptable answer!')
|
|
||||||
return commands[int(ans) - 1][1]
|
|
||||||
return add_options()
|
|
||||||
|
|
||||||
|
|
||||||
# This is used as the initial Menu
|
|
||||||
class MainMenu(BaseMenu):
|
|
||||||
|
|
||||||
def __init__(self, commands):
|
|
||||||
super(MainMenu, self).__init__(commands=commands)
|
|
@ -1,118 +0,0 @@
|
|||||||
# The MIT License (MIT)
|
|
||||||
#
|
|
||||||
# Copyright (c) 2016 Digital Sapphire
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
|
||||||
# in the Software without restriction, including without limitation the rights
|
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included in
|
|
||||||
# all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
# SOFTWARE.
|
|
||||||
import logging
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
from menus.exceptions import MenusError
|
|
||||||
|
|
||||||
# Preventing import errors on non windows
|
|
||||||
# platforms
|
|
||||||
if sys.platform == 'win32':
|
|
||||||
import msvcrt
|
|
||||||
else:
|
|
||||||
import termios
|
|
||||||
import tty
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
|
||||||
clear_screen_cmd = 'cls'
|
|
||||||
else:
|
|
||||||
clear_screen_cmd = 'clear'
|
|
||||||
|
|
||||||
|
|
||||||
def check_commands_else_raise(options):
|
|
||||||
# We need a least one thing to display
|
|
||||||
# Using this as a teaching aid. Also making the use of
|
|
||||||
# Engine(example=Ture) very explicit
|
|
||||||
if len(options) == 0:
|
|
||||||
msg = ('You must pass a menus object or initilize '
|
|
||||||
'like -> Engine(example=True)')
|
|
||||||
raise MenusError(msg, expected=True)
|
|
||||||
|
|
||||||
# We need a list or tuple to loop through
|
|
||||||
if not isinstance(options, list):
|
|
||||||
if not isinstance(options, tuple):
|
|
||||||
msg = ('You must pass a list or tuple to menus.')
|
|
||||||
raise MenusError(msg, expected=True)
|
|
||||||
|
|
||||||
if len(options) > 9:
|
|
||||||
msg = ('Cannot have more then 8 options per menu')
|
|
||||||
raise MenusError(msg, expected=True)
|
|
||||||
|
|
||||||
for o in options:
|
|
||||||
# Ensuring each item in list/tuple is a tuple
|
|
||||||
if not isinstance(o, tuple):
|
|
||||||
raise MenusError('Item must be tuple: {}'.format(o), expected=True)
|
|
||||||
|
|
||||||
if len(o) != 2:
|
|
||||||
raise MenusError('Invalid number of tuple '
|
|
||||||
'items:\n\n{}'.format(o))
|
|
||||||
# Ensure index 0 is a str
|
|
||||||
if not isinstance(o[0], six.string_types):
|
|
||||||
msg = 'Menus are passed as [("Menu Name", MenuObject())]'
|
|
||||||
raise MenusError(msg)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
# Gets a single character form standard input. Does not echo to the screen
|
|
||||||
class Getch(object):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
if sys.platform == 'win32':
|
|
||||||
self.impl = GetchWindows()
|
|
||||||
else:
|
|
||||||
self.impl = GetchUnix()
|
|
||||||
|
|
||||||
def __call__(self):
|
|
||||||
return self.impl()
|
|
||||||
|
|
||||||
|
|
||||||
class GetchUnix(object):
|
|
||||||
def __init__(self):
|
|
||||||
# Not sure if these imports are required here
|
|
||||||
# import tty, sys
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __call__(self):
|
|
||||||
fd = sys.stdin.fileno()
|
|
||||||
old_settings = termios.tcgetattr(fd)
|
|
||||||
try:
|
|
||||||
tty.setraw(sys.stdin.fileno())
|
|
||||||
ch = sys.stdin.read(1)
|
|
||||||
finally:
|
|
||||||
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
|
||||||
return ch
|
|
||||||
|
|
||||||
|
|
||||||
class GetchWindows(object):
|
|
||||||
def __init__(self):
|
|
||||||
# Not sure if this import is required
|
|
||||||
# import msvcrt
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __call__(self):
|
|
||||||
return msvcrt.getch()
|
|
Loading…
Reference in New Issue