Coverage for larch/shell.py: 0%
116 statements
« prev ^ index » next coverage.py v7.6.0, created at 2024-10-16 21:04 +0000
« prev ^ index » next coverage.py v7.6.0, created at 2024-10-16 21:04 +0000
1#!/usr/bin/env python
2"""
3Larch command-line shell
4"""
5import cmd
6import os
7import sys
8import signal
9from .interpreter import Interpreter
11from .site_config import history_file
12from .version import make_banner
13from .larchlib import StdWriter
14from .utils import uname
16HAS_READLINE = False
17try:
18 import readline
19 HAS_READLINE = True
20except ImportError:
21 pass
23HAS_WXPYTHON = False
24try:
25 import wx
26 HAS_WXPYTHON = True
27except ImportError:
28 wx = None
31class Shell(cmd.Cmd):
32 """command shell for Larch"""
33 def __init__(self, completekey='tab', debug=False, quiet=False,
34 stdin=None, stdout=None, banner_msg=None,
35 maxhist=25000, with_wx=False):
37 self.debug = debug
38 cmd.Cmd.__init__(self,completekey='tab')
39 if stdin is not None:
40 sys.stdin = stdin
41 if stdout is not None:
42 sys.stdout = stdout
43 self.stdin = sys.stdin
44 self.stdout = sys.stdout
46 if HAS_READLINE:
47 try:
48 readline.read_history_file(history_file)
49 except IOError:
50 print(f'could not read history from {history_file}')
53 self.larch = Interpreter(historyfile=history_file,
54 maxhistory=maxhist)
55 self.larch.writer = StdWriter(_larch=self.larch)
57 if with_wx and HAS_WXPYTHON:
58 symtable = self.larch.symtable
59 try:
60 from .wxlib import LarchWxApp
61 app = LarchWxApp(redirect=False, clearSigInt=False)
62 except SystemExit:
63 with_wx = False
65 symtable.set_symbol('_sys.wx.wxapp', app)
66 symtable.set_symbol('_sys.wx.force_wxupdate', False)
67 symtable.set_symbol('_sys.wx.parent', None)
69 from .wxlib import inputhook
70 symtable.set_symbol('_sys.wx.inputhook', inputhook)
71 if uname == 'darwin':
72 symtable.set_symbol('_sys.wx.ping', inputhook.ping_darwin)
73 else:
74 symtable.set_symbol('_sys.wx.ping', inputhook.ping)
76 inputhook.ON_INTERRUPT = self.onCtrlC
77 inputhook.WXLARCH_SYM = symtable
79 signal.signal(signal.SIGINT, self.onCtrlC)
80 self.prompt = self.larch.input.prompt
81 writer = self.larch.writer
82 self.color_writer = (uname != 'win' and hasattr(writer, 'set_textstyle'))
83 if not quiet:
84 if banner_msg is None:
85 banner_msg = make_banner(show_libraries=['numpy', 'scipy', 'matplotlib', 'h5py',
86 'lmfit', 'xraydb', 'wx','wxmplot'])
87 if self.color_writer:
88 writer.set_textstyle('error')
89 writer.write(banner_msg)
90 writer.write("\n")
91 if self.color_writer:
92 writer.set_textstyle('text')
94 self.larch_execute = self.default
95 self.larch.run_init_scripts()
97 def onCtrlC(self, *args, **kws):
98 self.larch.symtable.set_symbol('_sys.wx.keyboard_interrupt', True)
99 return 0
101 def on_exit(self, text=None):
102 "exit"
103 trim_last = False
104 if text is not None:
105 trim_last = text.strip() in ('quit', 'exit')
106 try:
107 self.larch.input.history.save(trim_last=trim_last)
108 except PermissionError:
109 print("Warning: could not save session history -- permission denied")
110 self.larch.symtable._plotter.close_all_displays()
111 sys.exit()
113 def do_exit(self, text):
114 "exit"
115 self.on_exit(text=text)
117 def do_quit(self, text):
118 "quit"
119 self.on_exit(text=text)
121 def emptyline(self):
122 pass
124 def onecmd(self, line):
125 "single command"
126 return self.default(line)
128 def do_help(self, arg):
129 "help"
130 if arg.startswith('(') and arg.endswith(')'):
131 arg = arg[1:-1]
132 elif arg.startswith("'") and arg.endswith("'"):
133 arg = arg[1:-1]
134 elif arg.startswith('"') and arg.endswith('"'):
135 arg = arg[1:-1]
136 self.default(f"help({arg})")
138 def do_shell(self, txt):
139 "shell command"
140 os.system(txt)
142 def default(self, line):
143 "default handler"
144 if line.strip() in ('quit', 'exit', 'quit()', 'exit()', 'EOF'):
145 self.on_exit(line)
146 ret = self.larch.eval(line, fname='<stdin>', lineno=0)
147 if self.larch.error:
148 self.larch.input.clear()
149 if self.color_writer:
150 self.larch.writer.set_textstyle('error')
151 self.larch.show_errors()
152 if self.color_writer:
153 self.larch.writer.set_textstyle('line')
154 if ret is not None:
155 self.larch.writer.write("%s\n" % repr(ret))
157 self.larch.writer.flush()
158 self.prompt = self.larch.input.next_prompt