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.
Completed
Push — master ( d26138...c5d2d5 )
by thatsIch
55s
created

RainmeterOpenPathsCommand.opn()   A

Complexity

Conditions 2

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 2
c 3
b 0
f 0
dl 0
loc 7
rs 9.4285
1
"""
2
Module for opening paths containing Rainmeter-specific or
3
Windows environment variables.
4
"""
5
6
import os
7
import re
8
import threading
9
10
import sublime
11
import sublime_plugin
12
13
from . import rainmeter
14
from . import logger
15
16
17
# Files to open with sublime instead of the system default
18
settings = sublime.load_settings("Rainmeter.sublime-settings")
19
defexts = settings.get("rainmeter_default_open_sublime_extensions", "")
20
21
if defexts is not None:
22
    defexts = defexts.strip().strip(r"|").strip()
23
else:
24
    defexts = ""
25
26
addexts = settings.get("rainmeter_open_sublime_extensions", "")
27
28
if addexts is not None:
29
    addexts = addexts.strip().strip(r"|").strip()
30
else:
31
    addexts = ""
32
33
sublime_files = re.compile("(?i).*\\.(" + addexts + "|" + defexts + ")\\b")
34
35
log = settings.get("rainmeter_enable_logging", False)
36
37
38
def _log(function, string):
39
    if log:
40
        print("rainmeter." + function + ": " + string)
41
42
43
def open_path(path, transient=False):
44
    """Try to open a file or folder path or URL in the system default
45
    application, or in Sublime if it's a text file.
46
47
    Use transient=True to open a file in Sublime without assigning it a tab.
48
    A tab will be created once the buffer is modified.
49
50
    Will return False if the path doesn't exist in the file system, and
51
    True otherwise.
52
53
    """
54
55
    if not path:
56
        return False
57
58
    if not os.path.exists(path):
59
        return False
60
61
    sublime.set_timeout(lambda: sublime.status_message("Opening " + path), 10)
62
    if sublime_files.search(path):
63
        if transient:
64
            sublime.set_timeout(
65
                lambda: sublime.active_window().open_file(path,
66
                                                          sublime.TRANSIENT),
67
                10)
68
        else:
69
            sublime.set_timeout(
70
                lambda: sublime.active_window().open_file(path),
71
                10)
72
    else:
73
        os.startfile(path)
74
75
    return True
76
77
78
def open_url(url):
79
    """Try opening a url with the system default for urls.
80
81
    Will return False if it's not a url, and True otherwise.
82
    """
83
    if re.match(r"(?i)(https?|ftp)://", url.strip()):
84
        os.startfile(url)
85
        sublime.set_timeout(lambda: sublime.status_message("Opening " + url),
86
                            10)
87
        return True
88
    else:
89
        return False
90
91
92
class TryOpenThread(threading.Thread):
93
94
    def __init__(self, line, region, opn):
95
        self.line = line
96
        self.region = region
97
        self.opn = opn
98
        threading.Thread.__init__(self)
99
100
    def run(self):
101
        # 1. Selected text
102
        selected = self.line[self.region.a:self.region.b]
103
        if self.opn(selected):
104
            _log("TryOpenThread.run", "Open selected text")
105
            return
106
107
        # 2. String enclosed in double quotes
108
109
        # Find the quotes before the current point (if any)
110
        lastquote = self.region.a - 1
111
        while lastquote >= 0 and self.line[lastquote] != "\"":
112
            lastquote -= 1
113
114
        if not lastquote < 0 and self.line[lastquote] == "\"":
115
            # Find the quote after the current point (if any)
116
            nextquote = self.region.b
117
            while nextquote == len(self.line) or self.line[nextquote] != "\"":
118
                nextquote += 1
119
120
            if not nextquote == len(self.line) \
121
                    and self.line[nextquote] == "\"":
122
                string = self.line[lastquote: nextquote].strip("\"")
123
                if self.opn(string):
124
                    _log("TryOpenThread.run", "Open string enclosed " +
125
                         "in quotes: " + string)
126
                    return
127
128
        # 3. Region from last whitespace to next whitespace
129
130
        # Find the space before the current point (if any)
131
        lastspace = self.region.a - 1
132
        while lastspace >= 0 \
133
                and self.line[lastspace] != " " \
134
                and self.line[lastspace] != "\t":
135
            lastspace -= 1
136
137
        # Set to zero if nothing was found until the start of the line
138
        if lastspace < 0:
139
            lastspace = 0
140
141
        if lastspace == 0 \
142
                or self.line[lastspace] == " " \
143
                or self.line[lastspace] == "\t":
144
            # Find the space after the current point (if any)
145
            nextspace = self.region.b
146
            while nextspace < len(self.line) \
147
                    and self.line[nextspace] != " " \
148
                    and self.line[nextspace] != "\t":
149
                nextspace += 1
150
151
            if nextspace >= len(self.line) \
152
                    or self.line[nextspace] == " " \
153
                    or self.line[nextspace] == "\t":
154
                string = self.line[lastspace: nextspace].strip()
155
                if self.opn(string):
156
                    _log("TryOpenThread.run", "Open string enclosed " +
157
                         "in whitespace: " + string)
158
                    return
159
160
        # 4. Everything after the first \"=\" until the end
161
        # of the line (strip quotes)
162
        mtch = re.search(r"=\s*(.*)\s*$", self.line)
163
        if mtch and self.opn(mtch.group(1).strip("\"")):
164
            _log("TryOpenThread.run", "Open text after \"=\": " +
165
                 mtch.group(1).strip("\""))
166
            return
167
168
        # 5. Whole line (strip comment character at start)
169
        stripmatch = re.search(r"^[ \t;]*?([^ \t;].*)\s*$", self.line)
170
        if self.opn(stripmatch.group(1)):
171
            _log("TryOpenThread.run", "Open whole line: " +
172
                 stripmatch.group(1))
173
            return
174
175
176
class RainmeterOpenPathsCommand(sublime_plugin.TextCommand):
177
178
    """Try to open paths on lines in the current selection.
179
180
    Will try to open paths to files, folders or URLs on each line in the
181
    current selection. To achieve this, the following substrings of each line
182
    intersecting the selection are tested:
183
184
    1. The string inside the selection
185
    2. The string between possible quotes preceding and following the
186
       selection, if any
187
    3. The string between the preceding and following whitespace
188
    4. Everything after the first "=" on the line until the end of the line
189
    5. The whole line, stripped of preceding semicolons
190
    """
191
192
    def __split_selection_by_new_lines(self, selection):
193
        # Split all regions into individual segments on lines (using nicely
194
        # confusing python syntax).
195
        return [
196
            j for i in [
197
                self.view.split_by_newlines(region)
198
                for region in selection
199
            ]
200
            for j in i
201
        ]
202
203
    def __open_each_line_by_thread(self, lines):
204
        """this identifies segments in selected lines
205
        and tries to open them in any way in a new thread.
206
        This can be resource intensive.
207
        """
208
        fnm = self.view.file_name()
209
210
        def opn(string):
211
            opened = open_path(rainmeter.make_path(string, fnm)) or open_url(string)
212
            if opened:
213
                logger.info(
214
                    __file__,
215
                    "run(self, edit)",
216
                    "found file or url '" + string + "' to open"
217
                )
218
219
        for linereg in lines:
220
            wholeline = self.view.line(linereg)
221
            thread = TryOpenThread(self.view.substr(wholeline),
222
                                   sublime.Region(linereg.a - wholeline.a,
223
                                                  linereg.b - wholeline.a),
224
                                   opn)
225
            thread.start()
226
227
    def run(self, _):
228
        # Detect various scenarios of file paths and try to open them one
229
        # after the other
230
        # @param edit unused
231
232
        selection = self.view.sel()
233
        lines = self.__split_selection_by_new_lines(selection)
234
235
        loaded_settings = sublime.load_settings("Rainmeter.sublime-settings")
236
        max_open_lines = loaded_settings.get("rainmeter_max_open_lines", 40)
237
238
        # Refuse if too many lines selected to avoid freezing
239
240
        if len(lines) > max_open_lines:
241
            accept = sublime.ok_cancel_dialog(
242
                "You are trying to open " +
243
                str(len(lines)) + " lines.\n" +
244
                "That's a lot, and could take some time. Try anyway?")
245
            if not accept:
246
                return
247
248
        self.__open_each_line_by_thread(lines)
249
250
    def is_enabled(self):
251
        # Check if current syntax is rainmeter
252
        israinmeter = self.view.score_selector(self.view.sel()[0].a,
253
                                               "source.rainmeter")
254
255
        return israinmeter > 0
256
257
    def is_visible(self):
258
        return self.is_enabled()
259