You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
4.7 KiB

7 years ago
7 years ago
7 years ago
7 years ago
  1. #!/usr/bin/python3
  2. from string import ascii_lowercase
  3. import argparse
  4. import itertools
  5. import os
  6. import re
  7. import cmd2
  8. from dictionary import DEFAULT, ALTERNATE
  9. from word_remove_dialog import RemoveWordsActivity
  10. LOWERCASE = set(ascii_lowercase)
  11. DICTS = {"default": DEFAULT, "alt": ALTERNATE}
  12. # argparsers
  13. dictionary_manage_parser = argparse.ArgumentParser()
  14. commands = dictionary_manage_parser.add_mutually_exclusive_group(required=True)
  15. commands.add_argument(
  16. "-l", "--list", action="store_true", help="List available dictionaries"
  17. )
  18. commands.add_argument("-s", "--switch", help="Dictionary to swap to")
  19. letter_set_manage = argparse.ArgumentParser()
  20. letter_set_manage.add_argument("letter", nargs="+")
  21. guessing = argparse.ArgumentParser()
  22. guessing.add_argument("pattern", help="Pattern to match")
  23. hide_exclude = argparse.ArgumentParser()
  24. commands = hide_exclude.add_mutually_exclusive_group(required=True)
  25. commands.add_argument(
  26. "-e",
  27. "--edit",
  28. help="Change which words will be hidden from view",
  29. action="store_true",
  30. )
  31. commands.add_argument(
  32. "-c", "--commit", help="Move excluded words to be hidden words", action="store_true"
  33. )
  34. commands.add_argument(
  35. "-s",
  36. "--show",
  37. help="Show which words are in the current exclude list",
  38. action="store_true",
  39. )
  40. def candidates(letters, min=2):
  41. possibilities = []
  42. for length in range(min, len(letters) + 1):
  43. for comb in itertools.combinations(letters, length):
  44. for perm in itertools.permutations(comb):
  45. word = "".join(perm)
  46. possibilities.append(word)
  47. return possibilities
  48. class MainLoop(cmd2.Cmd):
  49. """Loop for wordscape commands
  50. """
  51. prompt = "<{}> $ "
  52. def __init__(self):
  53. self.dict = "default"
  54. self.excludes = set()
  55. self.hidden = set()
  56. self.init_letters(input("Enter letters: "))
  57. self._candidates = None
  58. self._in_dictionary = None
  59. super().__init__()
  60. def init_letters(self, letters):
  61. if not isinstance(letters, str):
  62. letters = "".join(letters)
  63. letters = letters.lower()
  64. self.letters = [l for l in letters if l in LOWERCASE]
  65. self.prompt = MainLoop.prompt.format(", ".join(self.letters))
  66. self._candidates = None
  67. self._in_dictionary = None
  68. @property
  69. def candidates(self):
  70. if self._candidates is None:
  71. self._candidates = candidates(self.letters)
  72. return self._candidates
  73. @property
  74. def in_dictionary(self):
  75. if self._in_dictionary is None:
  76. self._in_dictionary = DICTS[self.dict].filter(self.candidates)
  77. return self._in_dictionary
  78. def filter(self, regex):
  79. matching_pattern = filter(regex.match, self.candidates)
  80. return DICTS[self.dict].filter(matching_pattern)
  81. @cmd2.with_argparser(dictionary_manage_parser)
  82. def do_dict(self, args):
  83. """list/switch dict"""
  84. if args.list:
  85. print(
  86. "\n".join(
  87. (
  88. "{} {}".format("*" if key == self.dict else " ", key)
  89. for key in DICTS.keys()
  90. )
  91. )
  92. )
  93. else:
  94. DICTS[args.switch]
  95. self.dict = args.switch
  96. @cmd2.with_argparser(letter_set_manage)
  97. def do_change_letters(self, args):
  98. """Change the letters on the board"""
  99. self.init_letters(args.letter)
  100. @cmd2.with_argparser(guessing)
  101. def do_find(self, args):
  102. """Find words that match a pattern"""
  103. pattern = re.compile(args.pattern + "$")
  104. matching_words = self.filter(pattern)
  105. app = RemoveWordsActivity(matching_words - self.hidden, self.excludes)
  106. if os.name == "nt":
  107. app.run(fork=False)
  108. else:
  109. app.run()
  110. was_canceled, new_exludes = app.get_results()
  111. if not was_canceled:
  112. self.excludes.update(new_exludes)
  113. @cmd2.with_argparser(hide_exclude)
  114. def do_hide(self, args):
  115. """Hide words that are in the exclude list"""
  116. if args.show:
  117. print("\n".join(sorted(self.excludes)))
  118. return
  119. if args.commit:
  120. self.hidden.update(self.excludes)
  121. self.excludes = set()
  122. return
  123. if args.edit:
  124. app = RemoveWordsActivity(self.excludes, self.hidden)
  125. if os.name == "nt":
  126. app.run(fork=False)
  127. else:
  128. app.run()
  129. was_canceled, results = app.get_results()
  130. if not was_canceled:
  131. result_set = set(results)
  132. self.excludes = self.hidden - result_set
  133. self.hidden = result_set
  134. return
  135. if __name__ == "__main__":
  136. MainLoop().cmdloop()