def EvalPrompt(self, val): """Perform the two evaluations that bash does. Used by $PS1 and ${x@P}.""" if val.tag != value_e.Str: return self.default_prompt # no evaluation necessary # Parse backslash escapes (cached) try: tokens = self.tokens_cache[val.s] except KeyError: tokens = list(match.PS1_LEXER.Tokens(val.s)) self.tokens_cache[val.s] = tokens # Replace values. ps1_str = self._ReplaceBackslashCodes(tokens) # Parse it like a double-quoted word (cached). TODO: This could be done on # mem.SetVar(), so we get the error earlier. # NOTE: This is copied from the PS4 logic in Tracer. try: ps1_word = self.parse_cache[ps1_str] except KeyError: w_parser = self.parse_ctx.MakeWordParserForPlugin(ps1_str) try: ps1_word = w_parser.ReadForPlugin() except util.ParseError as e: ps1_word = word.ErrorWord("<ERROR: Can't parse PS1: %s>", e) self.parse_cache[ps1_str] = ps1_word # Evaluate, e.g. "${debian_chroot}\u" -> '\u' val2 = self.ex.word_ev.EvalForPlugin(ps1_word) return val2.s
def _EvalPS4(self): """For set -x.""" val = self.mem.GetVar('PS4') assert val.tag == value_e.Str s = val.s if s: first_char, ps4 = s[0], s[1:] else: first_char, ps4 = '+', ' ' # default # NOTE: This cache is slightly broken because aliases are mutable! I think # that is more or less harmless though. try: ps4_word = self.parse_cache[ps4] except KeyError: # We have to parse this at runtime. PS4 should usually remain constant. w_parser = self.parse_ctx.MakeWordParserForPlugin(ps4) try: ps4_word = w_parser.ReadForPlugin() except util.ParseError as e: ps4_word = word.ErrorWord("<ERROR: Can't parse PS4: %s>", e) self.parse_cache[ps4] = ps4_word #print(ps4_word) # TODO: Repeat first character according process stack depth. Where is # that stored? In the executor itself? It should be stored along with # the PID. Need some kind of ShellProcessState or something. # # We should come up with a better mechanism. Something like $PROC_INDENT # and $OIL_XTRACE_PREFIX. # Prevent infinite loop when PS4 has command sub! assert self.exec_opts.xtrace # We shouldn't call this unless it's on! self.exec_opts.xtrace = False try: prefix = self.word_ev.EvalForPlugin(ps4_word) finally: self.exec_opts.xtrace = True return first_char, prefix.s