-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathrsense_completions.py
137 lines (100 loc) · 3.57 KB
/
rsense_completions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import sublime
import sublime_plugin
import subprocess
import re
import os
import tempfile
try:
# Python 3
import urllib.request as urllib_compat
from urllib.error import HTTPError, URLError
except (ImportError):
# Python 2
import urllib2 as urllib_compat
from urllib2 import HTTPError, URLError
# RUBY_METHOD_SEP_PATTERN = re.compile('[^.:]*$')
RUBY_METHOD_SEP_PATTERN = re.compile('((?<=\.).*)|((?<=::).*)')
class RsenseCompletions(sublime_plugin.EventListener):
def get_project(self, view):
fn = view.file_name()
project = view.window().folders()
if len(project) > 0:
return project[0]
elif fn is not None:
return fn
else:
return ""
def make_command(self, view, text, location, path):
textarr = text.split("\n")
textstring = ""
for t in textarr:
textstring.join([t, "\n"])
row, col = view.rowcol(location)
locstring = "".join([str(row), ":", str(col)])
rsense_com = "_rsense_commandline.rb "
detect_proj = self.get_project(view)
proj_str = " --project=%s " % detect_proj
filestring = " --filepath=%s " % path
text_str = " --text='%s' " % text
loc_str = " --location='%s' " % locstring
return "".join([rsense_com, proj_str, filestring, text_str, loc_str])
def run_command(self, command_string):
pipe = subprocess.Popen(command_string, shell=True, stdout=subprocess.PIPE)
output, error = pipe.communicate()
if error is not None:
print(error)
return output
def _sanitize_output(self, output):
return output.decode('utf-8')
def _parse_output(self, output):
lines = output.split("\n")
line_parts = [line.split(" ", 4) for line in lines]
return line_parts
def clean_and_arrange(self, output):
if output is None:
return []
completions = []
parsed = self._parse_output(self._sanitize_output(output).strip())
for line in parsed:
show_string = ""
candidate = []
if len(line) > 1:
for strng in line:
candidate.append(strng)
candidate.append(" ")
compl = line[0]
completions.append((show_string.join(candidate), compl))
return completions
# TODO: Filter completions for metadata returned by rsense.
def get_completions(self, view, text, location, path):
command_string = self.make_command(view, text, location, path)
raw_output = self.run_command(command_string)
return self.clean_and_arrange(raw_output)
def is_ruby_scope(self, view, location):
scopes = [
"source.ruby - comment",
"source.ruby.rspec - string - comment"
]
match = False
for scope in scopes:
if view.match_selector(location, scope):
match = True
return match
def on_query_completions(self, view, text, locations):
if locations is None:
return []
location = locations[0]
if not self.is_ruby_scope(view, location):
return []
row, col = view.rowcol(location)
line_start_offset = location - col
line_text = view.substr(sublime.Region(line_start_offset, location + 1))
if not RUBY_METHOD_SEP_PATTERN.search(line_text):
return []
text = view.substr(sublime.Region(0, view.size()))
if text is None:
return []
if view.settings().get("repl", False):
#logger.debug("Rsense does not complete in SublimeREPL views")
return
return self.get_completions(view, text, location, view.file_name())