GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

ContextSensAutoCompletion.__autocomplete_key()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 12
rs 9.4285
1
"""This module handles the whole auto smart completion sublime-rainmeter has to offer."""
2
3
# python libs
4
import re
5
6
# st libs
7
import sublime
8
9
# own libs
10
from .. import logger
11
from .skin.rainmeter_section import SkinRainmeterSectionAutoComplete
12
from .skin.metadata_section import SkinMetadataSectionAutoComplete
13
from .section import SkinSectionAutoCompleter
14
15
16
class ContextSensAutoCompletion(object):
17
    """
18
    This represents the internal implementation for the contextual auto completion.
19
20
    It uses smart environmental information like section, key, values etc
21
    to provide smarter auto completion suggestions.
22
    """
23
24
    # only show our completion list because nothing else makes sense in this context
25
    flags = sublime.INHIBIT_EXPLICIT_COMPLETIONS | sublime.INHIBIT_WORD_COMPLETIONS
26
27
    section = None
28
    skin_rainmeter_section = None
29
    skin_metadata_section = None
30
31
    scope = "source.rainmeter"
32
33
    # comments are specified by ';'
34
    comment_exp = re.compile(r'^\s*;.*')
35
36
    # enable searching for [] in multiline environment
37
    bracket_expression = re.compile(r'^\s*(\[.+\])\s*$', re.MULTILINE)
38
    section_expression = re.compile(r'^\s*\[(.+)\]\s*$', re.I)
39
    key_expression = re.compile(r'^\s*(.+)\s*=?\s*(.*?)\s*$', re.MULTILINE)
40
    key_value_expression = re.compile(r'^\s*(.+?)\s*=\s*(.*?)\s*$', re.MULTILINE)
41
42
    def __init__(self):
43
        """Initialize the different completer components."""
44
        self.section = SkinSectionAutoCompleter()
45
        self.skin_rainmeter_section = SkinRainmeterSectionAutoComplete()
46
        self.skin_metadata_section = SkinMetadataSectionAutoComplete()
47
48
    def get_lines_of_section_on_cursor(self, view, location):
49
        """Determine content of current section."""
50
        size = view.size()
51
        start_content = view.substr(sublime.Region(0, location))
52
        end_content = view.substr(sublime.Region(location, size))
53
54
        start_index = self.get_start_index_of_section(start_content)
55
        end_index = self.get_end_index_of_section(end_content, location, size)
56
57
        section = view.substr(sublime.Region(start_index, end_index))
58
        lines = section.splitlines()
59
60
        return start_index, lines
61
62
    def get_start_index_of_section(self, start_content):
63
        """
64
        Return the index of the section.
65
66
        If no section is found the first index (0) is returned
67
        """
68
        matches = list(self.bracket_expression.finditer(start_content))
69
70
        if len(matches) > 0:
71
            last_match = matches[-1]
72
            return last_match.start()
73
74
        # no previous section found, hardly legal but who cares
75
        else:
76
            return 0
77
78
    def get_end_index_of_section(self, end_content, offset, end_index):
79
        """
80
        Return the index of the next section.
81
82
        If no next section is found the last index is returned given through the param end_index
83
        """
84
        matches = list(self.bracket_expression.finditer(end_content))
85
        if len(matches) > 0:
86
            first_match = matches[0]
87
            return first_match.start() + offset
88
89
        # no next section found
90
        else:
91
            return end_index
92
93
    def get_key_value(self, line_content):
94
        """
95
        Extract the key and/or value in a line if existing.
96
97
        This is used if a specific completion is only shown
98
        on special conditions like only show X on measures.
99
100
        If nothing is given return (None, None)
101
        """
102
        key_value_match = self.key_value_expression.search(line_content)
103
        if key_value_match:
104
            key_match = key_value_match.group(1)
105
            value_match = key_value_match.group(2)
106
            logger.info(
107
                "key/value found in '" + line_content +
108
                "' with ('" + key_match + "', '" + value_match + "')"
109
            )
110
111
            return key_match, value_match
112
113
        key_only_match = self.key_expression.search(line_content)
114
        if key_only_match:
115
            logger.info("potential key found in '" + line_content + "'")
116
            return key_only_match.group(1), None
117
118
        return None, None
119
120
    def get_key_values(self, lines):
121
        """Extract all key values in the given lines."""
122
        key_values = []
123
124
        for line in lines:
125
            key, value = self.get_key_value(line)
126
            if key:
127
                key_values.append((key, value))
128
129
        return key_values
130
131
    def __autocomplete_value(self, line_content, section):
132
        key_match, value_match = self.get_key_value(line_content)
133
134
        if value_match == "":
135
            logger.info("auto-completing value: cursor after equal trigger in '" + line_content + "'")
136
            # value trigger
137
            return self.skin_rainmeter_section.get_value_context_completion(
138
                section,
139
                key_match
140
            )
141
142
    def __autocomplete_key(self, line_content, prefix, section, key_values):
143
        # only do key completion if we are in the key are
144
        # that means in front of the equal or no equal at all
145
        logger.info("before equal trigger in '" + line_content + "'")
146
        key_result = self.skin_rainmeter_section.get_key_context_completion(
147
            prefix,
148
            line_content,
149
            section,
150
            key_values
151
        )
152
153
        return key_result
154
155
    @classmethod
156
    def __autocomplete_default(cls):
157
        return None
158
159
    def on_query_completions(self, view, prefix, locations):
160
        """
161
        Execute if a auto completion is requested.
162
163
        can be either via typing or manual invoked with ctrl+space.
164
165
        This provides general variable extractions which are then
166
        passed to the domain specific worker completions.
167
        """
168
        for location in locations:
169
            # ignore non scope
170
            if not view.match_selector(location, self.scope):
171
                return None
172
173
            # ignore on comment lines
174
            cursor_line = view.line(location)
175
            line_content = view.substr(cursor_line)
176
            if self.comment_exp.search(line_content):
177
                logger.info("found comment")
178
                return None
179
180
            # find last occurance of the [] to determine the ini sections
181
            section_start_index, section_lines = self.get_lines_of_section_on_cursor(view, location)
182
183
            # determine auto completions of sections on double newline
184
            line_start_coord = cursor_line.begin()
185
            row, _ = view.rowcol(line_start_coord)
186
            section_start = view.rowcol(section_start_index)
187
            section_start_row, _ = section_start
188
189
            if row > 2:
190
                line_above_empty = section_lines[row - section_start_row - 1] == ''
191
                line_aabove_empty = section_lines[row - section_start_row - 2] == ''
192
193
                if line_above_empty and line_aabove_empty:
194
                    size = view.size()
195
                    content = view.substr(sublime.Region(0, size))
196
                    sections = self.bracket_expression.findall(content)
197
198
                    return self.section.get_key_context_completion(prefix, line_content, sections)
199
200
            # filter empty lines
201
            section_lines = [section_line for section_line in section_lines if section_line]
202
            # filter comments
203
            section_lines = [line for line in section_lines if not self.comment_exp.search(line)]
204
205
            if not section_lines:
206
                logger.info("section is empty")
207
                size = view.size()
208
                content = view.substr(sublime.Region(0, size))
209
                sections = self.bracket_expression.findall(content)
210
211
                return self.section.get_key_context_completion(prefix, line_content, sections)
212
213
            # extract section
214
            first_line = section_lines[0]
215
            match = self.section_expression.search(first_line)
216
217
            section = match.group(1)
218
            key_values = self.get_key_values(section_lines)
219
220
            return self.__autocomplete_value(line_content, section) or \
221
                self.__autocomplete_key(line_content, prefix, section, key_values) or \
222
                self.__autocomplete_default()
223