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

120 lines, 73 significant
1from __future__ import print_function
2
3from _devbuild.gen.runtime_asdl import scope_e
4from _devbuild.gen.syntax_asdl import loc
5from _devbuild.gen.value_asdl import (value, value_e)
6
7from core import error
8from core import state
9from display import ui
10from core import vm
11from frontend import args
12from frontend import flag_util
13from mycpp.mylib import log
14
15from typing import Dict, cast, TYPE_CHECKING
16if TYPE_CHECKING:
17 from _devbuild.gen.runtime_asdl import cmd_value
18 from core import optview
19
20_ = log
21
22
23class IsMain(vm._Builtin):
24 """is-main builtin.
25 """
26
27 def __init__(self, mem):
28 # type: (state.Mem) -> None
29 self.mem = mem
30
31 def Run(self, cmd_val):
32 # type: (cmd_value.Argv) -> int
33 return 0 if self.mem.is_main else 1
34
35
36class SourceGuard(vm._Builtin):
37 """source-guard builtin.
38
39 source-guard main || return
40 """
41
42 def __init__(self, guards, exec_opts, errfmt):
43 # type: (Dict[str, bool], optview.Exec, ui.ErrorFormatter) -> None
44 self.guards = guards
45 self.exec_opts = exec_opts
46 self.errfmt = errfmt
47
48 def Run(self, cmd_val):
49 # type: (cmd_value.Argv) -> int
50 _, arg_r = flag_util.ParseCmdVal('source-guard', cmd_val)
51 name, _ = arg_r.ReadRequired2('requires a name')
52 #log('guards %s', self.guards)
53 if name in self.guards:
54 # already defined
55 if self.exec_opts.redefine_module():
56 self.errfmt.PrintMessage(
57 '(interactive) Reloading source file %r' % name)
58 return 0
59 else:
60 return 1
61 self.guards[name] = True
62 return 0
63
64
65class Use(vm._Builtin):
66 """use bin, use dialect to control the 'first word'.
67
68 Examples:
69 use bin grep sed
70
71 use dialect ninja # I think it must be in a 'dialect' scope
72 use dialect travis
73 """
74
75 def __init__(self, mem, errfmt):
76 # type: (state.Mem, ui.ErrorFormatter) -> None
77 self.mem = mem
78 self.errfmt = errfmt
79
80 def Run(self, cmd_val):
81 # type: (cmd_value.Argv) -> int
82 arg_r = args.Reader(cmd_val.argv, locs=cmd_val.arg_locs)
83 arg_r.Next() # skip 'use'
84
85 arg, arg_loc = arg_r.Peek2()
86 if arg is None:
87 raise error.Usage("expected 'bin' or 'dialect'", loc.Missing)
88 arg_r.Next()
89
90 if arg == 'dialect':
91 expected, e_loc = arg_r.Peek2()
92 if expected is None:
93 raise error.Usage('expected dialect name', loc.Missing)
94
95 UP_actual = self.mem.GetValue('_DIALECT', scope_e.Dynamic)
96 if UP_actual.tag() == value_e.Str:
97 actual = cast(value.Str, UP_actual).s
98 if actual == expected:
99 return 0 # OK
100 else:
101 self.errfmt.Print_('Expected dialect %r, got %r' %
102 (expected, actual),
103 blame_loc=e_loc)
104
105 return 1
106 else:
107 # Not printing expected value
108 self.errfmt.Print_('Expected dialect %r' % expected,
109 blame_loc=e_loc)
110 return 1
111
112 # 'use bin' can be used for static analysis. Although could it also
113 # simplify the SearchPath logic? Maybe ensure that it is memoized?
114 if arg == 'bin':
115 rest = arg_r.Rest()
116 for name in rest:
117 log('bin %s', name)
118 return 0
119
120 raise error.Usage("expected 'bin' or 'dialect'", arg_loc)