1
1
import atexit
2
2
import importlib
3
3
import os .path
4
+ import platform
4
5
import traceback
5
6
import types
6
7
from typing import Any
20
21
)
21
22
BASILISP_REPL_HISTORY_LENGTH = 1000
22
23
REPL_INPUT_FILE_PATH = "<REPL Input>"
24
+ STDIN_INPUT_FILE_PATH = "<stdin>"
25
+ STDIN_FILE_NAME = "-"
23
26
24
27
25
28
try :
26
29
import readline
27
- except ImportError :
30
+ except ImportError : # pragma: no cover
28
31
pass
29
32
else :
30
33
readline .parse_and_bind ("tab: complete" )
34
37
try :
35
38
readline .read_history_file (BASILISP_REPL_HISTORY_FILE_PATH )
36
39
readline .set_history_length (BASILISP_REPL_HISTORY_LENGTH )
37
- except FileNotFoundError :
40
+ except FileNotFoundError : # pragma: no cover
38
41
pass
39
-
40
- atexit .register (readline .write_history_file , BASILISP_REPL_HISTORY_FILE_PATH )
42
+ except Exception : # noqa # pragma: no cover
43
+ # PyPy 3.6's ncurses implementation throws an error here
44
+ if platform .python_implementation () != "PyPy" :
45
+ raise
46
+ else :
47
+ atexit .register (readline .write_history_file , BASILISP_REPL_HISTORY_FILE_PATH )
41
48
42
49
43
50
@click .group ()
44
51
def cli ():
45
52
"""Basilisp is a Lisp dialect inspired by Clojure targeting Python 3."""
46
- pass
47
53
48
54
49
55
def eval_file (filename : str , ctx : compiler .CompilerContext , module : types .ModuleType ):
50
56
"""Evaluate a file with the given name into a Python module AST node."""
51
57
last = None
52
58
for form in reader .read_file (filename , resolver = runtime .resolve_alias ):
53
- last = compiler .compile_and_exec_form (form , ctx , module , filename )
59
+ last = compiler .compile_and_exec_form (form , ctx , module )
60
+ return last
61
+
62
+
63
+ def eval_stream (stream , ctx : compiler .CompilerContext , module : types .ModuleType ):
64
+ """Evaluate the forms in stdin into a Python module AST node."""
65
+ last = None
66
+ for form in reader .read (stream , resolver = runtime .resolve_alias ):
67
+ last = compiler .compile_and_exec_form (form , ctx , module )
54
68
return last
55
69
56
70
@@ -134,7 +148,7 @@ def repl(
134
148
lsrc = input (f"{ ns .name } => " )
135
149
except EOFError :
136
150
break
137
- except KeyboardInterrupt :
151
+ except KeyboardInterrupt : # pragma: no cover
138
152
print ("" )
139
153
continue
140
154
@@ -143,7 +157,7 @@ def repl(
143
157
144
158
try :
145
159
result = eval_str (lsrc , ctx , ns .module , eof )
146
- if result is eof :
160
+ if result is eof : # pragma: no cover
147
161
continue
148
162
print (runtime .lrepr (result ))
149
163
repl_module .mark_repl_result (result )
@@ -209,7 +223,11 @@ def run( # pylint: disable=too-many-arguments
209
223
"""Run a Basilisp script or a line of code, if it is provided."""
210
224
basilisp .init ()
211
225
ctx = compiler .CompilerContext (
212
- filename = CLI_INPUT_FILE_PATH if code else file_or_code ,
226
+ filename = CLI_INPUT_FILE_PATH
227
+ if code
228
+ else (
229
+ STDIN_INPUT_FILE_PATH if file_or_code == STDIN_FILE_NAME else file_or_code
230
+ ),
213
231
opts = {
214
232
compiler .WARN_ON_SHADOWED_NAME : warn_on_shadowed_name ,
215
233
compiler .WARN_ON_SHADOWED_VAR : warn_on_shadowed_var ,
@@ -222,16 +240,29 @@ def run( # pylint: disable=too-many-arguments
222
240
with runtime .ns_bindings (in_ns ) as ns :
223
241
if code :
224
242
print (runtime .lrepr (eval_str (file_or_code , ctx , ns .module , eof )))
243
+ elif file_or_code == STDIN_FILE_NAME :
244
+ print (
245
+ runtime .lrepr (
246
+ eval_stream (click .get_text_stream ("stdin" ), ctx , ns .module )
247
+ )
248
+ )
225
249
else :
226
250
print (runtime .lrepr (eval_file (file_or_code , ctx , ns .module )))
227
251
228
252
229
253
@cli .command (short_help = "run tests in a Basilisp project" )
230
254
@click .argument ("args" , nargs = - 1 )
231
- def test (args ):
255
+ def test (args ): # pragma: no cover
232
256
"""Run tests in a Basilisp project."""
233
257
pytest .main (args = list (args ))
234
258
235
259
260
+ @cli .command (short_help = "print the version of Basilisp" )
261
+ def version ():
262
+ from basilisp .__version__ import __version__
263
+
264
+ print (f"Basilisp { __version__ } " )
265
+
266
+
236
267
if __name__ == "__main__" :
237
268
cli ()
0 commit comments