This repository was archived by the owner on Mar 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathfsi.py
125 lines (109 loc) · 3.74 KB
/
fsi.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
from subprocess import Popen, PIPE
from os import path
import string
import threading
import tempfile
import uuid
import hidewin
try:
from queue import Queue
except:
from Queue import Queue
class FSharpInteractive:
def __init__(self, fsi_path, is_debug = False):
self._debug = is_debug
#self.logfiledir = tempfile.gettempdir() + "/log.txt"
#self.logfile = open(self.logfiledir, "w")
id = 'vim-' + str(uuid.uuid4())
if " " in fsi_path.strip():
command = fsi_path.split() + ['--fsi-server:%s' % id, '--nologo']
else:
command = [fsi_path, '--fsi-server:%s' % id, '--nologo']
opts = { 'stdin': PIPE, 'stdout': PIPE, 'stderr': PIPE, 'shell': False, 'universal_newlines': True }
hidewin.addopt(opts)
try:
self.p = Popen(command, **opts)
except Exception as e:
raise Exception ('Error executing fsi. g:fsharp_interactive_bin="' + fsi_path + '" ' + str(e))
if is_debug:
logfiledir = tempfile.gettempdir() + "/fsi-log.txt"
self.logfile = open(logfiledir, "w")
self._should_work = True
self.lines = Queue()
self.worker = threading.Thread(target=self._work, args=[])
self.worker.daemon = True
self.worker.start()
self.err_worker = threading.Thread(target=self._err_work, args=[])
self.err_worker.daemon = True
self.err_worker.start()
x = self.purge()
self._current_path = None
def _log(self, msg):
if self._debug:
self.logfile.write(msg + "\n")
self.logfile.flush()
def shutdown(self):
"""Shutdown fsi process"""
print("shutting down fsi")
self._should_work = False
try:
self.p.kill()
except:
pass
def set_loc(self, path, line_num):
self.p.stdin.write("#" + str(line_num) + " @\"" + path + "\"\n")
self.p.stdin.flush()
def send(self, txt):
self.p.stdin.write(txt + "\n")
self.p.stdin.write(";;\n")
self.p.stdin.flush()
self._log(">" + txt + ";;")
def cd(self, path):
if self._current_path == path:
return
self.p.stdin.write("System.IO.Directory.SetCurrentDirectory(@\"" + path + "\");;\n")
self.p.stdin.write("#silentCd @\"" + path + "\";;\n")
self.p.stdin.flush()
self.purge()
self._current_path = path
def purge(self):
items = []
while(True):
try:
l = self.lines.get(False).rstrip()
if 'SERVER-PROMPT>' not in l:
items.append(l)
except:
break
return items
def read_until_prompt(self, time_out):
output = []
try:
l = self.lines.get(True, time_out)
if 'SERVER-PROMPT>' in l:
return output
output.append(str(l).rstrip())
while(True):
l = self.read_one()
if 'SERVER-PROMPT>' in l:
return output
output.append(str(l).rstrip())
return output
except Exception as ex:
output.append(".....") #indicate that there may be more lines of output
return output
def read_one(self):
return self.lines.get(True, 0.5)
def _work(self):
while(self._should_work):
try:
l = self.p.stdout.readline()
self.lines.put(l, True)
self._log(l)
except Exception as ex:
print(ex)
def _err_work(self):
while(self._should_work):
l = self.p.stderr.readline()
self.lines.put(l, True)
self._log( "err: " + l)