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",
|