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 ( 3564e3...755d19 )
by thatsIch
01:00
created

RainmeterOpenPathsCommand.run()   F

Complexity

Conditions 9

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 9
c 2
b 0
f 0
dl 0
loc 47
rs 3.3333

1 Method

Rating   Name   Duplication   Size   Complexity  
A RainmeterOpenPathsCommand.opn() 0 7 2
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 run(self, edit):
193
        # Detect various scenarios of file paths and try to open them one
194
        # after the other
195
196
        fnm = self.view.file_name()
197
198
        def opn(st):
199
            opened = open_path(rainmeter.make_path(st, fnm)) or open_url(st)
200
            if opened:
201
                logger.info(
202
                    __file__,
203
                    "run(self, edit)",
204
                    "found file or url '" + st + "' to open"
205
                )
206
207
        selection = self.view.sel()
208
209
        # Split all regions into individual segments on lines (using nicely
210
        # confusing python syntax).
211
        lines = [
212
            j for i in [
213
                self.view.split_by_newlines(region)
214
                for region in selection
215
            ]
216
            for j in i
217
        ]
218
219
        loaded_settings = sublime.load_settings("Rainmeter.sublime-settings")
220
        max_open_lines = loaded_settings.get("rainmeter_max_open_lines", 40)
221
222
        # Refuse if too many lines selected to avoid freezing
223
224
        if len(lines) > max_open_lines:
225
            accept = sublime.ok_cancel_dialog(
226
                "You are trying to open " +
227
                str(len(lines)) + " lines.\n" +
228
                "That's a lot, and could take some time. Try anyway?")
229
            if not accept:
230
                return
231
232
        for linereg in lines:
233
            wholeline = self.view.line(linereg)
234
            thread = TryOpenThread(self.view.substr(wholeline),
235
                                   sublime.Region(linereg.a - wholeline.a,
236
                                                  linereg.b - wholeline.a),
237
                                   opn)
238
            thread.start()
239
240
    def is_enabled(self):
241
        # Check if current syntax is rainmeter
242
        israinmeter = self.view.score_selector(self.view.sel()[0].a,
243
                                               "source.rainmeter")
244
245
        return israinmeter > 0
246
247
    def is_visible(self):
248
        return self.is_enabled()
249