| @@ 26-111 (lines=86) @@ | ||
| 23 | from .yaml_content_reader import YamlContentReader |
|
| 24 | ||
| 25 | ||
| 26 | class SkinSectionAutoCompleter(YamlContentReader): # pylint: disable=R0903; only provide one method |
|
| 27 | """Ths class is the logical state holder for the auto completion suggestions. |
|
| 28 | ||
| 29 | Upon the request the respective yaml file is parsed and converted into a logical |
|
| 30 | representation of the completions. Depending on the prior information the completions |
|
| 31 | can be filtered containing less entries. |
|
| 32 | """ |
|
| 33 | ||
| 34 | def __get_completions(self): |
|
| 35 | """IO access to the yaml file. |
|
| 36 | ||
| 37 | Uses a yaml loader to parse it into a python object. |
|
| 38 | """ |
|
| 39 | try: |
|
| 40 | section_content = self._get_yaml_content("completion/", "section.yaml") |
|
| 41 | section = yaml.load(section_content) |
|
| 42 | ||
| 43 | return section |
|
| 44 | ||
| 45 | except yaml.YAMLError as error: |
|
| 46 | logger.error(error) |
|
| 47 | return [] |
|
| 48 | ||
| 49 | def __lazy_initialize_completions(self): |
|
| 50 | # use lazy initialization because else the API is not available yet |
|
| 51 | if not self.all_completions: |
|
| 52 | self.all_completions = self.__get_completions() |
|
| 53 | self.all_key_completions = compile_keys(self.all_completions) |
|
| 54 | ||
| 55 | def __filter_completions_by_sec(self, sections): |
|
| 56 | # filter by already existing keys |
|
| 57 | completions = [] |
|
| 58 | ||
| 59 | settings = sublime.load_settings("Rainmeter.sublime-settings") |
|
| 60 | allow_duplicates = settings.get("allow_completion_section_duplicates", False) |
|
| 61 | ||
| 62 | for completion in self.all_key_completions: |
|
| 63 | # trigger is not used here |
|
| 64 | section_id, display, content, unique = completion |
|
| 65 | ||
| 66 | # we only need to search for duplicates |
|
| 67 | # if we are having a unique section like [Rainmeter] |
|
| 68 | # and not allow duplicates |
|
| 69 | if unique and not allow_duplicates: |
|
| 70 | contained = 0 |
|
| 71 | # value not used here |
|
| 72 | for section in sections: |
|
| 73 | if section.casefold() == section_id.casefold(): |
|
| 74 | contained = 1 |
|
| 75 | break |
|
| 76 | ||
| 77 | if contained == 0: |
|
| 78 | completions.append((display, content)) |
|
| 79 | else: |
|
| 80 | completions.append((display, content)) |
|
| 81 | ||
| 82 | return completions |
|
| 83 | ||
| 84 | # only show our completion list because nothing else makes sense in this context |
|
| 85 | flags = sublime.INHIBIT_EXPLICIT_COMPLETIONS | sublime.INHIBIT_WORD_COMPLETIONS |
|
| 86 | ||
| 87 | all_completions = None |
|
| 88 | all_key_completions = None |
|
| 89 | ||
| 90 | def get_key_context_completion(self, prefix, line_content, sections): |
|
| 91 | """Provide all possible sections without duplicates of unique ones.""" |
|
| 92 | # if section.casefold() != "Metadata".casefold(): |
|
| 93 | # return None |
|
| 94 | ||
| 95 | self.__lazy_initialize_completions() |
|
| 96 | completions = self.__filter_completions_by_sec(sections) |
|
| 97 | # no results, means all keys are used up |
|
| 98 | if not completions: |
|
| 99 | return None |
|
| 100 | ||
| 101 | # only show sorted by distance if something was already typed |
|
| 102 | # because distance to empty string makes no sense |
|
| 103 | if line_content != "": |
|
| 104 | # sort by levenshtein distance |
|
| 105 | sorted_completions = sorted( |
|
| 106 | completions, |
|
| 107 | key=lambda completion: levenshtein(completion[1], prefix) |
|
| 108 | ) |
|
| 109 | return sorted_completions, self.flags |
|
| 110 | else: |
|
| 111 | return completions, self.flags |
|
| 112 | ||
| @@ 15-94 (lines=80) @@ | ||
| 12 | from ..yaml_content_reader import YamlContentReader |
|
| 13 | ||
| 14 | ||
| 15 | class SkinMetadataSectionAutoComplete(YamlContentReader): # pylint: disable=R0903; only provide one method |
|
| 16 | """This uses the provided YAML files to extract the possible completions.""" |
|
| 17 | ||
| 18 | def __get_completions(self): |
|
| 19 | try: |
|
| 20 | skin_metadata_section_content = self._get_yaml_content( |
|
| 21 | "completion/skin/", |
|
| 22 | "metadata_section.yaml" |
|
| 23 | ) |
|
| 24 | skin_metadata_section = yaml.load(skin_metadata_section_content) |
|
| 25 | ||
| 26 | return skin_metadata_section |
|
| 27 | ||
| 28 | except yaml.YAMLError as error: |
|
| 29 | logger.error(error) |
|
| 30 | return [] |
|
| 31 | ||
| 32 | def __lazy_initialize_completions(self): |
|
| 33 | # use lazy initialization because else the API is not available yet |
|
| 34 | if not self.all_completions: |
|
| 35 | self.all_completions = self.__get_completions() |
|
| 36 | self.all_key_completions = compile_keys(self.all_completions) |
|
| 37 | ||
| 38 | def __filter_completions_by_keys(self, keyvalues): |
|
| 39 | """ |
|
| 40 | In Rainmeter a key can only be used once in a section statement. |
|
| 41 | ||
| 42 | If you declare it twice this is a code smell. |
|
| 43 | """ |
|
| 44 | # filter by already existing keys |
|
| 45 | completions = [] |
|
| 46 | ||
| 47 | for completion in self.all_key_completions: |
|
| 48 | dummy_key, display, content, dummy_unique = completion |
|
| 49 | ||
| 50 | contained = 0 |
|
| 51 | # value not used here |
|
| 52 | for key, _ in keyvalues: |
|
| 53 | if key.casefold() == content.casefold(): |
|
| 54 | contained = 1 |
|
| 55 | break |
|
| 56 | ||
| 57 | if contained == 0: |
|
| 58 | completions.append((display, content)) |
|
| 59 | ||
| 60 | return completions |
|
| 61 | ||
| 62 | # only show our completion list because nothing else makes sense in this context |
|
| 63 | flags = sublime.INHIBIT_EXPLICIT_COMPLETIONS | sublime.INHIBIT_WORD_COMPLETIONS |
|
| 64 | ||
| 65 | all_completions = None |
|
| 66 | all_key_completions = None |
|
| 67 | ||
| 68 | def get_key_context_completion(self, prefix, line_content, section, keyvalues): |
|
| 69 | """ |
|
| 70 | Get context completion for a key. |
|
| 71 | ||
| 72 | This implies that it was entered in a non-key row. |
|
| 73 | """ |
|
| 74 | if section.casefold() != "Metadata".casefold(): |
|
| 75 | return None |
|
| 76 | ||
| 77 | self.__lazy_initialize_completions() |
|
| 78 | completions = self.__filter_completions_by_keys(keyvalues) |
|
| 79 | ||
| 80 | # no results, means all keys are used up |
|
| 81 | if not completions: |
|
| 82 | logger.info("no results, all keys are used up") |
|
| 83 | return None |
|
| 84 | ||
| 85 | # only show sorted by distance if something was already typed |
|
| 86 | # because distance to empty string makes no sense |
|
| 87 | if line_content != "": |
|
| 88 | # sort by levenshtein distance |
|
| 89 | sorted_completions = sorted( |
|
| 90 | completions, key=lambda completion: levenshtein(completion[1], prefix) |
|
| 91 | ) |
|
| 92 | return sorted_completions, self.flags |
|
| 93 | else: |
|
| 94 | return completions, self.flags |
|
| 95 | ||