diff options
-rw-r--r-- | flake.nix | 1 | ||||
-rw-r--r-- | src/pollyanna/arbitrary.py | 48 | ||||
-rw-r--r-- | src/pollyanna/pollyanna.py | 34 | ||||
-rw-r--r-- | src/setup.py | 2 |
4 files changed, 77 insertions, 8 deletions
diff --git a/flake.nix b/flake.nix index 553f483..fbbf696 100644 --- a/flake.nix +++ b/flake.nix @@ -35,6 +35,7 @@ gst-plugins-base gst-plugins-good ]) ++ (with pkgs.python3Packages; [ + more-itertools requests pygobject3 ]); diff --git a/src/pollyanna/arbitrary.py b/src/pollyanna/arbitrary.py new file mode 100644 index 0000000..fbaba4c --- /dev/null +++ b/src/pollyanna/arbitrary.py @@ -0,0 +1,48 @@ +from more_itertools import peekable +import re + + +class ArbitraryParser: + """Matches command strings with %s in them denoting arbitrary phrases""" + + def __init__(self): + self.all_words = [] + self.all_words.append("amazing") + self.all_words.append("this") + self.all_words.append("is") + self.all_words.append("a") + self.all_words.append("test") + self.all_words.append("of") + self.all_words.append("pollyana") + self.all_words.append("voice") + self.all_words.append("typing") + self.all_words.append("fuck") + self.all_words.append("yeah") + + def match(self, command, text_line): + """ + Determine whether a line of input text matches a command that has %s + in it. Commands without %s may be passed, and will never match. + + Returns None if no match, or a list of the words that matched the %s + if one was found. + + Only a single %s is supported and it must be at the end of the + command. + """ + + command_words = re.split(r'[,\s-]+', command.strip()) + text_words = re.split(r'[,\s-]+', text_line.strip()) + + text_iter = peekable(text_words) + for word in command_words: + is_text_end = text_iter.peek(default=None) == None + if word == '%s': + if not is_text_end: + return list(text_iter) + else: + return None + elif is_text_end or word != next(text_iter): + return None + + return None diff --git a/src/pollyanna/pollyanna.py b/src/pollyanna/pollyanna.py index 295a1e5..b1ad38d 100644 --- a/src/pollyanna/pollyanna.py +++ b/src/pollyanna/pollyanna.py @@ -9,6 +9,7 @@ import os.path import subprocess from gi.repository import GObject, GLib +from pollyanna.arbitrary import ArbitraryParser from pollyanna.recognizer import Recognizer from pollyanna.util import * from pollyanna.numbers import NumberParser @@ -26,8 +27,9 @@ class Pollyanna: self.options = vars(self.config.options) self.commands = self.options['commands'] - # Create number parser for later use + # Create parsers for later use self.number_parser = NumberParser() + self.arbitrary_parser = ArbitraryParser() # Create a hasher self.hasher = Hasher(self.config) @@ -88,10 +90,13 @@ class Pollyanna: with open(self.config.strings_file, 'w') as strings: # Add command words to the corpus for voice_cmd in sorted(self.commands.keys()): - strings.write(voice_cmd.strip().replace('%d', '') + "\n") + strings.write(re.sub(r'%[ds]', '', voice_cmd.strip()) + "\n") # Add number words to the corpus for word in self.number_parser.number_words: strings.write(word + " ") + # Add dictionary words for arbitrary substrings to the corpus + for word in self.arbitrary_parser.all_words: + strings.write(word + " ") strings.write("\n") def log_history(self, text): @@ -139,11 +144,26 @@ class Pollyanna: self.run_command(cmd) self.log_history(text) else: - # Run the invalid_sentence_command if it's set - if self.options['invalid_sentence_command']: - subprocess.call(self.options['invalid_sentence_command'], - shell=True) - print("no matching command {0}".format(t)) + is_matched = False + for command in self.commands: + match_result = self.arbitrary_parser.match(command, t) + if match_result != None: + is_matched = True + break + if is_matched: + cmd = self.commands[command] + cmd = cmd.format(' '.join(match_result)) + # Should we be passing words? + if self.options['pass_words']: + cmd += " " + t + self.run_command(cmd) + self.log_history(text) + else: + # Run the invalid_sentence_command if it's set + if self.options['invalid_sentence_command']: + subprocess.call(self.options['invalid_sentence_command'], + shell=True) + print("no matching command {0}".format(t)) # If there is a UI and we are not continuous listen if self.ui: if not self.continuous_listen: diff --git a/src/setup.py b/src/setup.py index 347e5cf..d778f06 100644 --- a/src/setup.py +++ b/src/setup.py @@ -25,7 +25,7 @@ setup( "Programming Language :: Python :: 3.5", "Topic :: Home Automation" ], - install_requires=["requests"], + install_requires=["more-itertools", "requests"], data_files = [ ("/usr/share/pollyanna", ["data/icon.png", "data/icon_small.png", |