| 1 |  |  | """This module handles the skin section auto completion. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | This provides the means to automatically add the base rainmeter sections | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | upon auto complete request with: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | * [Rainmeter] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | * [Metadata] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | * [Variables] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | * [Measure] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | * [Meter] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | * [MeterStyle] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | This only activates if the file is empty or at least 2 new lines above the current caret. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | import yaml | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | import sublime | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  | from .. import logger | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | from .levenshtein import levenshtein | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | from .compiler import compile_keys | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  | from .yaml_content_reader import YamlContentReader | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |  | 
            
                                                                                                            
                            
            
                                                                    
                                                                                                        
            
            
                | 26 |  | View Code Duplication | 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 |  |  |  |