forked from jcartledge/sublime-worksheet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathworksheet.py
122 lines (102 loc) · 3.99 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
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
# Make sure /usr/local/bin is on the path
exec_path = os.getenv('PATH', '')
if not "/usr/local/bin" in exec_path:
os.environ["PATH"] = exec_path + os.pathsep + "/usr/local/bin"
class WorksheetCommand(sublime_plugin.TextCommand):
def run(self, edit):
self.load_settings()
try:
language = self.get_language()
default_def = self.settings.get("worksheet_defaults")
repl_defs = self.settings.get("worksheet_languages")
repl_def = dict(
list(default_def.items()) + list(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(e.message)
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_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),
100
)
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" + e.message)
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)