#!/usr/bin/python3 from string import ascii_lowercase import argparse import itertools import os import re import cmd2 from dictionary import DEFAULT, ALTERNATE from word_remove_dialog import RemoveWordsActivity LOWERCASE = set(ascii_lowercase) DICTS = {"default": DEFAULT, "alt": ALTERNATE} # argparsers dictionary_manage_parser = argparse.ArgumentParser() commands = dictionary_manage_parser.add_mutually_exclusive_group(required=True) commands.add_argument( "-l", "--list", action="store_true", help="List available dictionaries" ) commands.add_argument("-s", "--switch", help="Dictionary to swap to") letter_set_manage = argparse.ArgumentParser() letter_set_manage.add_argument("letter", nargs="+") guessing = argparse.ArgumentParser() guessing.add_argument("pattern", help="Pattern to match") hide_exclude = argparse.ArgumentParser() commands = hide_exclude.add_mutually_exclusive_group(required=True) commands.add_argument( "-e", "--edit", help="Change which words will be hidden from view", action="store_true", ) commands.add_argument( "-c", "--commit", help="Move excluded words to be hidden words", action="store_true" ) commands.add_argument( "-s", "--show", help="Show which words are in the current exclude list", action="store_true", ) def candidates(letters, min=2): possibilities = [] for length in range(min, len(letters) + 1): for comb in itertools.combinations(letters, length): for perm in itertools.permutations(comb): word = "".join(perm) possibilities.append(word) return possibilities class MainLoop(cmd2.Cmd): """Loop for wordscape commands """ prompt = "<{}> $ " def __init__(self): self.dict = "default" self.excludes = set() self.hidden = set() self.init_letters(input("Enter letters: ")) self._candidates = None self._in_dictionary = None super().__init__() def init_letters(self, letters): if not isinstance(letters, str): letters = "".join(letters) letters = letters.lower() self.letters = [l for l in letters if l in LOWERCASE] self.prompt = MainLoop.prompt.format(", ".join(self.letters)) self._candidates = None self._in_dictionary = None @property def candidates(self): if self._candidates is None: self._candidates = candidates(self.letters) return self._candidates @property def in_dictionary(self): if self._in_dictionary is None: self._in_dictionary = DICTS[self.dict].filter(self.candidates) return self._in_dictionary def filter(self, regex): matching_pattern = filter(regex.match, self.candidates) return DICTS[self.dict].filter(matching_pattern) @cmd2.with_argparser(dictionary_manage_parser) def do_dict(self, args): """list/switch dict""" if args.list: print( "\n".join( ( "{} {}".format("*" if key == self.dict else " ", key) for key in DICTS.keys() ) ) ) else: DICTS[args.switch] self.dict = args.switch @cmd2.with_argparser(letter_set_manage) def do_change_letters(self, args): """Change the letters on the board""" self.init_letters(args.letter) @cmd2.with_argparser(guessing) def do_find(self, args): """Find words that match a pattern""" pattern = re.compile(args.pattern + "$") matching_words = self.filter(pattern) app = RemoveWordsActivity(matching_words - self.hidden, self.excludes) if os.name == "nt": app.run(fork=False) else: app.run() was_canceled, new_exludes = app.get_results() if not was_canceled: self.excludes.update(new_exludes) @cmd2.with_argparser(hide_exclude) def do_hide(self, args): """Hide words that are in the exclude list""" if args.show: print("\n".join(sorted(self.excludes))) return if args.commit: self.hidden.update(self.excludes) self.excludes = set() return if args.edit: app = RemoveWordsActivity(self.excludes, self.hidden) if os.name == "nt": app.run(fork=False) else: app.run() was_canceled, results = app.get_results() if not was_canceled: result_set = set(results) self.excludes = self.hidden - result_set self.hidden = result_set return if __name__ == "__main__": MainLoop().cmdloop()