-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathworksheet.py
131 lines (110 loc) · 4.52 KB
/
worksheet.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
import sublime
import sublime_plugin
import os
from sys import version_info
PY3K = version_info >= (3, 0, 0)
if PY3K:
from .edit import Edit
from . import repl
else:
from edit import Edit
import repl
if sublime.platform() != 'windows':
# Make sure /usr/local/bin is on the path
exec_path = os.getenv('PATH', '').split(os.pathsep)
if not "/usr/local/bin" in exec_path:
os.environ["PATH"] = os.pathsep.join(exec_path + ["/usr/local/bin"])
class WorksheetCommand(sublime_plugin.TextCommand):
def run(self, edit):
self.load_settings()
try:
language = self.get_language()
default_def = self.get_repl_settings()
repl_defs = self.settings.get("worksheet_languages")
project_repl_defs = self.project_settings.get("worksheet_languages", {})
repl_def = dict(
list(default_def) + list(project_repl_defs.get(language, repl_defs.get(language, {})).items()))
filename = self.view.file_name()
if filename is not None:
repl_def["cwd"] = os.path.dirname(filename)
self.repl = repl.get_repl(language, repl_def)
except repl.ReplStartError as e:
return sublime.error_message(str(e))
self.remove_previous_results(edit)
def load_settings(self):
self.settings = sublime.load_settings("worksheet.sublime-settings")
self.timeout = self.settings.get("worksheet_timeout")
def get_repl_settings(self):
default_def = self.settings.get("worksheet_defaults")
if not hasattr(self, "project_settings"):
self.project_settings = {}
project_def = self.project_settings.get("worksheet_defaults", {})
settings = []
for key, setting in default_def.items():
settings.append((key, project_def.get(key, setting)))
return settings
def get_language(self):
return self.view.settings().get("syntax").split('/')[-1].split('.')[0]
def remove_previous_results(self, edit):
if not PY3K:
edit = self.view.begin_edit("remove_previous_results")
for region in reversed(self.view.find_all("^" + self.repl.prefix)):
self.view.erase(edit, self.view.full_line(region))
if not PY3K:
self.view.end_edit(edit)
def ensure_trailing_newline(self, edit):
eof = self.view.size()
if len(self.view.substr(self.view.line(eof)).strip()) is not 0:
self.view.insert(edit, eof, "\n")
def process_line(self, start):
line = self.view.full_line(start)
line_text = self.view.substr(line)
if "\n" in line_text:
self.view.add_regions("worksheet", list([line]), "string")
self.set_status("Sending 1 line to %(language)s REPL.")
self.queue_thread(
repl.ReplThread(self.repl, line_text),
line.end(),
).start()
else:
self.cleanup()
def queue_thread(self, thread, start):
sublime.set_timeout(lambda: self.handle_thread(thread, start), 5)
return thread
def handle_thread(self, thread, next_start):
if thread.is_alive():
self.handle_running_thread(thread, next_start)
else:
self.handle_finished_thread(thread, next_start)
def handle_running_thread(self, thread, next_start):
self.set_status("Waiting for %(language)s REPL.")
self.queue_thread(thread, next_start)
def handle_finished_thread(self, thread, next_start):
self.view.add_regions("worksheet", list(), "string")
result = thread.result
self.insert(result, next_start)
next_start += len(str(result))
if not result.terminates:
self.process_line(next_start)
else:
self.cleanup()
def insert(self, text, start):
with Edit(self.view) as edit:
edit.insert(start, str(text))
def set_status(self, msg, key="worksheet"):
self.view.set_status(key, msg % {"language": self.get_language()})
def cleanup(self):
self.set_status('')
try:
self.repl.close()
except repl.ReplCloseError as e:
sublime.error_message(
"Could not close the REPL:\n" + str(e))
class WorksheetEvalCommand(WorksheetCommand):
def run(self, edit):
WorksheetCommand.run(self, edit)
self.ensure_trailing_newline(edit)
self.process_line(0)
class WorksheetClearCommand(WorksheetCommand):
def run(self, edit):
WorksheetCommand.run(self, edit)