Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Theme update & plugin! (Preset & custom persistent) themes) #1087

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 24 additions & 23 deletions jarviscli/CmdInterpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,15 @@
import traceback
from cmd import Cmd
from functools import partial

from colorama import Fore

from packages.memory.memory import Memory
from PluginManager import PluginManager
from utilities import schedule
from utilities.animations import SpinnerThread
from utilities.GeneralUtilities import get_parent_directory
from utilities.GeneralUtilities import get_parent_directory, theme_option
from utilities.notification import notify
from utilities.voice import create_voice


class JarvisAPI(object):
"""
Jarvis interface for plugins.
Expand All @@ -42,7 +39,7 @@ def say(self, text, color="", speak=True):
e.g. Fore.BLUE
:param speak: False-, if text shouldn't be spoken even if speech is enabled
"""
print(color + text + Fore.RESET, flush=True)
print(color + text + theme_option('reset_text'), flush=True)

if speak:
self._jarvis.speak(text)
Expand All @@ -53,7 +50,7 @@ def input(self, prompt="", color=""):
"""
# we can't use input because for some reason input() and color codes do not work on
# windows cmd
sys.stdout.write(color + prompt + Fore.RESET)
sys.stdout.write(color + prompt + theme_option('reset_text'))
sys.stdout.flush()
text = sys.stdin.readline()
# return without newline
Expand Down Expand Up @@ -137,7 +134,7 @@ def cancel(self, schedule_id):
self._jarvis.scheduler.cancel(schedule_id)

spinner.stop()
self.say('Cancellation successful', Fore.GREEN)
self.say('Cancellation successful', theme_option('positive_text'))

# Voice wrapper
def enable_voice(self):
Expand Down Expand Up @@ -233,11 +230,13 @@ def spinner_start(self, message="Starting "):
self.spinner = SpinnerThread(message, 0.15)
self.spinner.start()

def spinner_stop(self, message="Task executed successfully! ", color=Fore.GREEN):
def spinner_stop(self, message="Task executed successfully! ", color=""):
"""
Function for stopping the spinner when prompted from a plugin
and displaying the message after completing the task
"""
color = theme_option('positive_text')

self.spinner.stop()
self.say(message, color)
self.spinner_running = False
Expand Down Expand Up @@ -275,8 +274,8 @@ def incorrect_option(self):
A function to notify the user that an incorrect option
has been entered and prompting him to enter a correct one
"""
self.say("Oops! Looks like you entered an incorrect option", Fore.RED)
self.say("Look at the options once again:", Fore.GREEN)
self.say("Oops! Looks like you entered an incorrect option", theme_option('negative_text'))
self.say("Look at the options once again:", theme_option('info'))


def catch_all_exceptions(do, pass_self=True):
Expand All @@ -290,12 +289,12 @@ def try_do(self, s):
if self._api.is_spinner_running():
self.spinner_stop("It seems some error has occured")
print(
Fore.RED
theme_option('negative_text')
+ "Some error occurred, please open an issue on github!")
print("Here is error:")
print('')
traceback.print_exc()
print(Fore.RESET)
print(theme_option('reset_text'))
return try_do


Expand All @@ -315,6 +314,7 @@ def __init__(
This constructor contains a dictionary with Jarvis Actions (what Jarvis can do).
In alphabetically order.
"""

Cmd.__init__(self)
command = " ".join(sys.argv[1:]).strip()
self.first_reaction = first_reaction
Expand Down Expand Up @@ -346,8 +346,8 @@ def __init__(
self.speech = create_voice(
self, gtts_status, rate=self.speech_rate)
except Exception as e:
self.say("Voice not supported", Fore.RED)
self.say(str(e), Fore.RED)
self.say("Voice not supported", theme_option('negative_text'))
self.say(str(e), theme_option('info'))

self.fixed_responses = {"what time is it": "clock",
"where am i": "pinpoint",
Expand All @@ -364,20 +364,21 @@ def __init__(

if self.first_reaction:
self._api.say(self.first_reaction_text)
self.first_reaction = False # DEBUG, MIGHT BE USELESS

def _init_plugin_info(self):
plugin_status_formatter = {
"disabled": len(self._plugin_manager.get_disabled()),
"enabled": self._plugin_manager.get_number_plugins_loaded(),
"red": Fore.RED,
"blue": Fore.BLUE,
"reset": Fore.RESET
"info": theme_option('info'),
"text": theme_option('default_text'),
"reset": theme_option('reset_text')
}

plugin_status = "{red}{enabled} {blue}plugins loaded"
plugin_status = "{info}{enabled} {text}plugins loaded"
if plugin_status_formatter['disabled'] > 0:
plugin_status += " {red}{disabled} {blue}plugins disabled. More information: {red}status\n"
plugin_status += Fore.RESET
plugin_status += " {info}{disabled} {text}plugins disabled. More information: {info}status\n"
plugin_status += theme_option('reset_text')

self.first_reaction_text += plugin_status.format(
**plugin_status_formatter)
Expand Down Expand Up @@ -428,7 +429,7 @@ def close(self):
if self._api.is_spinner_running():
self._api.spinner_stop('Some error has occured')

self.say("Goodbye, see you later!", Fore.RED)
self.say("Goodbye, see you later!", theme_option('greeting'))
self.scheduler.stop_all()
sys.exit()

Expand All @@ -438,7 +439,7 @@ def execute_once(self, command):

def error(self):
"""Jarvis let you know if an error has occurred."""
self.say("I could not identify your command...", Fore.RED)
self.say("I could not identify your command...", theme_option('negative_text'))

def interrupt_handler(self, signal, frame):
"""Closes Jarvis on SIGINT signal. (Ctrl-C)"""
Expand Down Expand Up @@ -469,7 +470,7 @@ def do_help(self, arg):
headerString = "These are valid commands for Jarvis"
formatString = "Format: command ([aliases for command])"
self.say(headerString)
self.say(formatString, Fore.BLUE)
self.say(formatString, theme_option('info'))
pluginDict = self._plugin_manager.get_plugins()
uniquePlugins = {}
for key in pluginDict.keys():
Expand Down
59 changes: 32 additions & 27 deletions jarviscli/Jarvis.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@
import re
import sys
import tempfile
from utilities.GeneralUtilities import print_say
from utilities.GeneralUtilities import print_say, theme_option
from CmdInterpreter import CmdInterpreter

# register hist path
HISTORY_FILENAME = tempfile.TemporaryFile('w+t')


PROMPT_CHAR = '~>'

"""
Expand All @@ -29,32 +27,38 @@
the actual location of our laptops.
"""


class Jarvis(CmdInterpreter, object):
# variable used at Breakpoint #1.
# allows Jarvis say "Hi", only at the first interaction.
"""
variable used at Breakpoint #1.
allows Jarvis say "Hi", only at the first interaction.
specified colors are immediately overwritten, but is
kept to ensure nothing accidentally breaks
"""
first_reaction_text = ""
first_reaction_text += Fore.BLUE + \
'Jarvis\' sound is by default disabled.' + Fore.RESET
first_reaction_text += "\n"
first_reaction_text += Fore.BLUE + 'In order to let Jarvis talk out loud type: '
first_reaction_text += Fore.RESET + Fore.RED + 'enable sound' + Fore.RESET
first_reaction_text += "\n"
first_reaction_text += Fore.BLUE + \
"Type 'help' for a list of available actions." + Fore.RESET
first_reaction_text += "\n"
prompt = (
Fore.RED
+ "{} Hi, what can I do for you?\n".format(PROMPT_CHAR)
+ Fore.RESET)
prompt = ()

# Used to store user specific data

def __init__(self, first_reaction_text=first_reaction_text,
prompt=prompt, first_reaction=True,
directories=["jarviscli/plugins", "custom"]):

directories = self._rel_path_fix(directories)

# Reset first_reaction_text on init in order to change theme
first_reaction_text += theme_option('default_text') + \
'Jarvis\' sound is by default disabled.' + theme_option('reset_text')
first_reaction_text += "\n"
first_reaction_text += theme_option('default_text') + 'In order to let Jarvis talk out loud type: '
first_reaction_text += theme_option('reset_text') + theme_option('info') + 'enable sound' + theme_option('reset_text')
first_reaction_text += "\n"
first_reaction_text += theme_option('default_text') + \
"Type " + theme_option('info') + " 'help' " + "for a list of available actions." + theme_option('reset_text')
first_reaction_text += "\n"
prompt = (
theme_option('greeting')
+ "{} Hi, what can I do for you?\n".format(PROMPT_CHAR)
+ theme_option('reset_text'))

if sys.platform == 'win32':
self.use_rawinput = False
self.regex_dot = re.compile('\\.(?!\\w)')
Expand All @@ -79,7 +83,7 @@ def _rel_path_fix(self, dirs):

def default(self, data):
"""Jarvis let's you know if an error has occurred."""
print_say("I could not identify your command...", self, Fore.RED)
print_say("I could not identify your command...", self, theme_option('negative_text'))

def precmd(self, line):
"""Hook that executes before every command."""
Expand All @@ -104,12 +108,13 @@ def precmd(self, line):

def postcmd(self, stop, line):
"""Hook that executes after every command."""
if self.first_reaction:
self.prompt = (
Fore.RED
# if self.first_reaction:
self.prompt = (
theme_option('greeting')
+ "{} What can I do for you?\n".format(PROMPT_CHAR)
+ Fore.RESET)
self.first_reaction = False
+ theme_option('reset_text'))
# self.first_reaction = False

if self.enable_voice:
self.speech.text_to_speech("What can I do for you?\n")

Expand All @@ -128,7 +133,7 @@ def parse_input(self, data):

# input sanitisation to not mess up urls / numbers
data = self.regex_dot.sub("", data)

# Check if Jarvis has a fixed response to this data
if data in self.fixed_responses:
output = self.fixed_responses[data]
Expand Down
1 change: 1 addition & 0 deletions jarviscli/data/user_theme.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"current": {"greeting": "\u001b[32m", "default_text": "\u001b[37m", "info": "\u001b[31m", "negative_text": "\u001b[31m", "positive_text": "\u001b[32m", "reset_text": "\u001b[37m"}, "default": {"greeting": "\u001b[31m", "default_text": "\u001b[34m", "info": "\u001b[31m", "negative_text": "\u001b[31m", "positive_text": "\u001b[32m", "reset_text": "\u001b[39m"}, "blurple": {"greeting": "\u001b[35m", "default_text": "\u001b[36m", "info": "\u001b[34m", "negative_text": "\u001b[31m", "positive_text": "\u001b[32m", "reset_text": "\u001b[39m"}, "colorless": {"greeting": "\u001b[39m", "default_text": "\u001b[39m", "info": "\u001b[39m", "negative_text": "\u001b[39m", "positive_text": "\u001b[39m", "reset_text": "\u001b[39m"}, "lightmode": {"greeting": "\u001b[31m", "default_text": "\u001b[30m", "info": "\u001b[34m", "negative_text": "\u001b[31m", "positive_text": "\u001b[32m", "reset_text": "\u001b[39m"}, "darkmode": {"greeting": "\u001b[37m", "default_text": "\u001b[39m", "info": "\u001b[32m", "negative_text": "\u001b[31m", "positive_text": "\u001b[32m", "reset_text": "\u001b[39m"}, "evil": {"greeting": "\u001b[33m", "default_text": "\u001b[31m", "info": "\u001b[33m", "negative_text": "\u001b[31m", "positive_text": "\u001b[32m", "reset_text": "\u001b[31m"}, "agent-smith": {"greeting": "\u001b[32m", "default_text": "\u001b[37m", "info": "\u001b[31m", "negative_text": "\u001b[31m", "positive_text": "\u001b[32m", "reset_text": "\u001b[37m"}}
Loading