OILS / builtin / method_io.py View on Github | oilshell.org

172 lines, 89 significant
1"""Methods on IO type"""
2from __future__ import print_function
3
4from _devbuild.gen.value_asdl import value, value_e, value_t
5
6from core import error
7from core import num
8from core import state
9from core import vm
10from mycpp.mylib import log, NewDict
11from osh import prompt
12
13from typing import Dict, List, cast, TYPE_CHECKING
14if TYPE_CHECKING:
15 from frontend import typed_args
16 from osh import cmd_eval
17
18_ = log
19
20EVAL_NULL = 1
21EVAL_DICT = 2
22
23
24class Eval(vm._Callable):
25 """
26 These are similar:
27
28 var cmd = ^(echo hi)
29 call io->eval(cmd)
30
31 Also give the top namespace
32
33 call io->evalToDict(cmd)
34
35 TODO: remove eval (c)
36
37 The CALLER must handle errors.
38 """
39
40 def __init__(self, cmd_ev, which):
41 # type: (cmd_eval.CommandEvaluator, int) -> None
42 self.cmd_ev = cmd_ev
43 self.which = which
44
45 def Call(self, rd):
46 # type: (typed_args.Reader) -> value_t
47 unused = rd.PosValue()
48 cmd = rd.PosCommand()
49
50 dollar0 = rd.NamedStr("dollar0", None)
51 pos_args_raw = rd.NamedList("pos_args", None)
52 vars_ = rd.NamedDict("vars", None)
53 rd.Done()
54
55 pos_args = None # type: List[str]
56 if pos_args_raw is not None:
57 pos_args = []
58 for arg in pos_args_raw:
59 if arg.tag() != value_e.Str:
60 raise error.TypeErr(
61 arg, "Expected pos_args to be a List of Strs",
62 rd.LeftParenToken())
63
64 pos_args.append(cast(value.Str, arg).s)
65
66 if self.which == EVAL_NULL:
67 with state.ctx_Eval(self.cmd_ev.mem, dollar0, pos_args, vars_):
68 unused_status = self.cmd_ev.EvalCommand(cmd)
69 return value.Null
70
71 elif self.which == EVAL_DICT:
72 # TODO: dollar0, pos_args, vars_ not supposed
73 # Does ctx_FrontFrame has different scoping rules? For "vars"?
74
75 bindings = NewDict() # type: Dict[str, value_t]
76 with state.ctx_FrontFrame(self.cmd_ev.mem, bindings):
77 unused_status = self.cmd_ev.EvalCommand(cmd)
78 return value.Dict(bindings)
79
80 else:
81 raise AssertionError()
82
83
84class CaptureStdout(vm._Callable):
85
86 def __init__(self, shell_ex):
87 # type: (vm._Executor) -> None
88 self.shell_ex = shell_ex
89
90 def Call(self, rd):
91 # type: (typed_args.Reader) -> value_t
92
93 unused = rd.PosValue()
94 cmd = rd.PosCommand()
95 rd.Done() # no more args
96
97 status, stdout_str = self.shell_ex.CaptureStdout(cmd)
98 if status != 0:
99 # Note that $() raises error.ErrExit with the status.
100 # But I think that results in a more confusing error message, so we
101 # "wrap" the errors.
102 properties = {
103 'status': num.ToBig(status)
104 } # type: Dict[str, value_t]
105 raise error.Structured(
106 4, 'captureStdout(): command failed with status %d' % status,
107 rd.LeftParenToken(), properties)
108
109 return value.Str(stdout_str)
110
111
112class PromptVal(vm._Callable):
113 """
114 _io->promptVal('$') is like \$
115 It expands to $ or # when root
116 """
117
118 def __init__(self, prompt_ev):
119 # type: (prompt.Evaluator) -> None
120 self.prompt_ev = prompt_ev
121
122 def Call(self, rd):
123 # type: (typed_args.Reader) -> value_t
124
125 # "self" param is guaranteed to succeed
126 unused = rd.PosValue()
127 what = rd.PosStr()
128 rd.Done() # no more args
129
130 # Bug fix: protect against crash later in PromptVal()
131 if len(what) != 1:
132 raise error.Expr(
133 'promptVal() expected a single char, got %r' % what,
134 rd.LeftParenToken())
135
136 return value.Str(self.prompt_ev.PromptVal(what))
137
138
139# TODO: Implement these
140
141
142class Time(vm._Callable):
143
144 def __init__(self):
145 # type: () -> None
146 pass
147
148 def Call(self, rd):
149 # type: (typed_args.Reader) -> value_t
150 return value.Null
151
152
153class Strftime(vm._Callable):
154
155 def __init__(self):
156 # type: () -> None
157 pass
158
159 def Call(self, rd):
160 # type: (typed_args.Reader) -> value_t
161 return value.Null
162
163
164class Glob(vm._Callable):
165
166 def __init__(self):
167 # type: () -> None
168 pass
169
170 def Call(self, rd):
171 # type: (typed_args.Reader) -> value_t
172 return value.Null