Esempio n. 1
0
def AppBundleMain(argv):
    login_shell = False

    b = os_path.basename(argv[0])
    main_name, ext = os_path.splitext(b)
    if main_name.startswith('-'):
        login_shell = True
        main_name = main_name[1:]

    if main_name == 'oil' and ext:  # oil.py or oil.ovm
        try:
            first_arg = argv[1]
        except IndexError:
            raise args.UsageError('Missing required applet name.')

        if first_arg in ('-h', '--help'):
            builtin.Help(['bundle-usage'], pyutil.GetResourceLoader())
            sys.exit(0)

        if first_arg in ('-V', '--version'):
            _ShowVersion()
            sys.exit(0)

        main_name = first_arg
        if main_name.startswith('-'):  # TODO: Remove duplication above
            login_shell = True
            main_name = main_name[1:]
        argv0 = argv[1]
        main_argv = argv[2:]
    else:
        argv0 = argv[0]
        main_argv = argv[1:]

    if main_name in ('osh', 'sh'):
        status = ShellMain('osh', argv0, main_argv, login_shell)
        _tlog('done osh main')
        return status
    elif main_name == 'oshc':
        try:
            return OshCommandMain(main_argv)
        except args.UsageError as e:
            ui.Stderr('oshc usage error: %s', e.msg)
            return 2

    elif main_name == 'oil':
        return ShellMain('oil', argv0, main_argv, login_shell)
    elif main_name == 'wok':
        return WokMain(main_argv)
    elif main_name == 'boil':
        return BoilMain(main_argv)

    # For testing latency
    elif main_name == 'true':
        return 0
    elif main_name == 'false':
        return 1
    elif main_name == 'readlink':
        return readlink.main(main_argv)
    else:
        raise args.UsageError('Invalid applet name %r.' % main_name)
Esempio n. 2
0
  def GetSpecForName(self, argv0):
    """
    Args:
      argv0: A finished argv0 to lookup
    """
    pair = self.lookup.get(argv0)  # NOTE: Could be ''
    if pair:
      return pair

    key = os_path.basename(argv0)
    pair = self.lookup.get(key)
    if pair:
      return pair

    for glob_pat, base_opts, user_spec in self.patterns:
      #log('Matching %r %r', key, glob_pat)
      if libc.fnmatch(glob_pat, key):
        return base_opts, user_spec

    return None, None
Esempio n. 3
0
    def GetSpecForName(self, argv0):
        """
    Args:
      argv0: A finished argv0 to lookup
    """
        user_spec = self.lookup.get(argv0)  # NOTE: Could be ''
        if user_spec:
            return user_spec

        key = os_path.basename(argv0)
        actions = self.lookup.get(key)
        if user_spec:
            return user_spec

        for glob_pat, base_opts, user_spec in self.patterns:
            #log('Matching %r %r', key, glob_pat)
            if libc.fnmatch(glob_pat, key):
                return base_opts, user_spec

        # Nothing matched
        return self.lookup['__fallback']
Esempio n. 4
0
    def Matches(self, comp):
        # type: (Api) -> List[str]
        # Have to clear the response every time.  TODO: Reuse the object?
        state.SetGlobalArray(self.cmd_ev.mem, 'COMPREPLY', [])

        # New completions should use COMP_ARGV, a construct specific to OSH>
        state.SetGlobalArray(self.cmd_ev.mem, 'COMP_ARGV', comp.partial_argv)

        # Old completions may use COMP_WORDS.  It is split by : and = to emulate
        # bash's behavior.
        # More commonly, they will call _init_completion and use the 'words' output
        # of that, ignoring COMP_WORDS.
        comp_words = []
        for a in comp.partial_argv:
            AdjustArg(a, [':', '='], comp_words)
        if comp.index == -1:  # cmopgen
            comp_cword = comp.index
        else:
            comp_cword = len(comp_words) - 1  # weird invariant

        state.SetGlobalArray(self.cmd_ev.mem, 'COMP_WORDS', comp_words)
        state.SetGlobalString(self.cmd_ev.mem, 'COMP_CWORD', str(comp_cword))
        state.SetGlobalString(self.cmd_ev.mem, 'COMP_LINE', comp.line)
        state.SetGlobalString(self.cmd_ev.mem, 'COMP_POINT', str(comp.end))

        argv = [comp.first, comp.to_complete, comp.prev]
        self.log('Running completion function %r with arguments %s',
                 self.func.name, argv)

        self.comp_lookup.ClearCommandsChanged()
        status = self.cmd_ev.RunFuncForCompletion(self.func, argv)
        commands_changed = self.comp_lookup.GetCommandsChanged()

        self.log('comp.first %s, commands_changed: %s', comp.first,
                 commands_changed)

        if status == 124:
            cmd = os_path.basename(comp.first)
            if cmd in commands_changed:
                self.log('Got status 124 from %r and %s commands changed',
                         self.func.name, commands_changed)
                raise _RetryCompletion()
            else:
                # This happens with my own completion scripts.  bash doesn't show an
                # error.
                self.log(
                    "Function %r returned 124, but the completion spec for %r wasn't "
                    "changed", self.func.name, cmd)
                return []

        # Read the response.
        # NOTE: 'COMP_REPLY' would follow the naming convention!
        val = state.GetGlobal(self.cmd_ev.mem, 'COMPREPLY')
        if val.tag_() == value_e.Undef:
            # We set it above, so this error would only happen if the user unset it.
            # Not changing it means there were no completions.
            # TODO: This writes over the command line; it would be better to use an
            # error object.
            stderr_line('osh: Ran function %r but COMPREPLY was unset',
                        self.func.name)
            return []

        if val.tag_() != value_e.MaybeStrArray:
            log('ERROR: COMPREPLY should be an array, got %s', val)
            return []
        self.log('COMPREPLY %s', val)

        # Return this all at once so we don't have a generator.  COMPREPLY happens
        # all at once anyway.
        return val.strs
Esempio n. 5
0
    def _ReplaceBackslashCodes(self, tokens):
        # type: (List[Tuple[Id_t, str]]) -> str
        ret = []  # type: List[str]
        non_printing = 0
        for id_, value in tokens:
            # BadBacklash means they should have escaped with \\.  TODO: Make it an error.
            # 'echo -e' has a similar issue.
            if id_ in (Id.PS_Literals, Id.PS_BadBackslash):
                ret.append(value)

            elif id_ == Id.PS_Octal3:
                i = int(value[1:], 8)
                ret.append(chr(i % 256))

            elif id_ == Id.PS_LBrace:
                non_printing += 1
                ret.append('\x01')

            elif id_ == Id.PS_RBrace:
                non_printing -= 1
                if non_printing < 0:  # e.g. \]\[
                    return PROMPT_ERROR

                ret.append('\x02')

            elif id_ == Id.PS_Subst:  # \u \h \w etc.
                ch = value[1:]
                if ch == '$':  # So the user can tell if they're root or not.
                    r = self.cache.Get('$')

                elif ch == 'u':
                    r = self.cache.Get('user')

                elif ch == 'h':
                    hostname = self.cache.Get('hostname')
                    # foo.com -> foo
                    r, _ = mylib.split_once(hostname, '.')

                elif ch == 'H':
                    r = self.cache.Get('hostname')

                elif ch == 'w':
                    try:
                        pwd = state.GetString(self.mem, 'PWD')
                        home = state.MaybeString(
                            self.mem, 'HOME')  # doesn't have to exist
                        # Shorten to ~/mydir
                        r = ui.PrettyDir(pwd, home)
                    except error.Runtime as e:
                        r = '<Error: %s>' % e.UserErrorString()

                elif ch == 'W':
                    val = self.mem.GetValue('PWD')
                    if val.tag_() == value_e.Str:
                        str_val = cast(value__Str, val)
                        r = os_path.basename(str_val.s)
                    else:
                        r = '<Error: PWD is not a string> '

                else:
                    r = consts.LookupCharPrompt(ch)

                    # TODO: Handle more codes
                    # R(r'\\[adehHjlnrstT@AuvVwW!#$\\]', Id.PS_Subst),
                    if r is None:
                        r = r'<Error: \%s not implemented in $PS1> ' % ch

                # See comment above on bash hack for $.
                ret.append(r.replace('$', '\\$'))

            else:
                raise AssertionError('Invalid token %r' % id_)

        # mismatched brackets, see https://github.com/oilshell/oil/pull/256
        if non_printing != 0:
            return PROMPT_ERROR

        return ''.join(ret)
Esempio n. 6
0
def AppBundleMain(argv):
    # type: (List[str]) -> int

    # NOTE: This has a side effect of deleting _OVM_* from the environment!
    loader = pyutil.GetResourceLoader()

    b = os_path.basename(argv[0])
    main_name, ext = os_path.splitext(b)

    arg_r = args.Reader(argv)
    if main_name == 'oil' and ext:  # oil.py or oil.ovm
        arg_r.Next()
        first_arg = arg_r.Peek()
        if first_arg is None:
            raise error.Usage('Missing required applet name.')

        if first_arg in ('-h', '--help'):
            errfmt = None  # not needed here
            help_builtin = builtin_misc.Help(loader, errfmt)
            help_builtin.Run(pure.MakeBuiltinArgv(['bundle-usage']))
            sys.exit(0)

        if first_arg in ('-V', '--version'):
            pyutil.ShowAppVersion('Oil', loader)
            sys.exit(0)

        main_name = first_arg

    login_shell = False
    if main_name.startswith('-'):
        login_shell = True
        main_name = main_name[1:]

    if main_name in ('osh', 'sh'):
        # TODO:
        # - Initialize a different shell if line_input isn't present
        status = shell.Main('osh', arg_r, posix.environ, login_shell, loader,
                            line_input)

        _tlog('done osh main')
        return status

    elif main_name == 'osh-pure':
        # TODO: pure.Main()
        pass

    elif main_name == 'oshc':
        arg_r.Next()
        main_argv = arg_r.Rest()
        try:
            return OshCommandMain(main_argv)
        except error.Usage as e:
            stderr_line('oshc usage error: %s', e.msg)
            return 2

    elif main_name == 'oil':
        return shell.Main('oil', arg_r, posix.environ, login_shell, loader,
                          line_input)

    elif main_name == 'tea':
        main_argv = arg_r.Rest()
        return TeaMain(main_argv)

    # For testing latency
    elif main_name == 'true':
        return 0
    elif main_name == 'false':
        return 1
    elif main_name == 'readlink':
        main_argv = arg_r.Rest()
        return readlink.main(main_argv)
    else:
        raise error.Usage('Invalid applet name %r.' % main_name)
Esempio n. 7
0
    def _ReplaceBackslashCodes(self, tokens):
        # type: (List[Tuple[Id, str]]) -> str
        ret = []
        non_printing = 0
        for id_, value in tokens:
            # BadBacklash means they should have escaped with \\.  TODO: Make it an error.
            # 'echo -e' has a similar issue.
            if id_ in (Id.PS_Literals, Id.PS_BadBackslash):
                ret.append(value)

            elif id_ == Id.PS_Octal3:
                i = int(value[1:], 8)
                ret.append(chr(i % 256))

            elif id_ == Id.PS_LBrace:
                non_printing += 1
                ret.append('\x01')

            elif id_ == Id.PS_RBrace:
                non_printing -= 1
                if non_printing < 0:  # e.g. \]\[
                    return PROMPT_ERROR

                ret.append('\x02')

            elif id_ == Id.PS_Subst:  # \u \h \w etc.
                char = value[1:]
                if char == '$':  # So the user can tell if they're root or not.
                    r = '#' if self.cache.Get('euid') == 0 else '$'

                elif char == 'u':
                    r = self.cache.Get('user')

                elif char == 'h':
                    r = self.cache.Get('hostname').split('.')[0]

                elif char == 'H':
                    r = self.cache.Get('hostname')

                elif char == 'w':
                    val = self.mem.GetVar('PWD')
                    if val.tag == value_e.Str:
                        # Shorten to ~/mydir
                        r = ui.PrettyDir(val.s, self.mem.GetVar('HOME'))
                    else:
                        r = '<Error: PWD is not a string> '

                elif char == 'W':
                    val = self.mem.GetVar('PWD')
                    if val.tag == value_e.Str:
                        r = os_path.basename(val.s)
                    else:
                        r = '<Error: PWD is not a string> '

                elif char in _ONE_CHAR:
                    r = _ONE_CHAR[char]

                else:
                    r = r'<Error: \%s not implemented in $PS1> ' % char

                # See comment above on bash hack for $.
                ret.append(r.replace('$', '\\$'))

            else:
                raise AssertionError('Invalid token %r' % id_)

        # mismatched brackets, see https://github.com/oilshell/oil/pull/256
        if non_printing != 0:
            return PROMPT_ERROR

        return ''.join(ret)
Esempio n. 8
0
    def _ReplaceBackslashCodes(self, tokens):
        ret = []
        non_printing = 0
        for id_, value in tokens:
            # BadBacklash means they should have escaped with \\, but we can't
            # make this an error.
            if id_ in (Id.PS_Literals, Id.PS_BadBackslash):
                ret.append(value)

            elif id_ == Id.PS_Octal3:
                i = int(value[1:], 8)
                ret.append(chr(i % 256))

            elif id_ == Id.PS_LBrace:
                non_printing += 1

            elif id_ == Id.PS_RBrace:
                non_printing -= 1

            elif id_ == Id.PS_Subst:  # \u \h \w etc.
                char = value[1:]
                if char == '$':  # So the user can tell if they're root or not.
                    r = '#' if self.cache.Get('euid') == 0 else '$'

                elif char == 'u':
                    r = self.cache.Get('user')

                elif char == 'h':
                    r = self.cache.Get('hostname').split('.')[0]

                elif char == 'H':
                    r = self.cache.Get('hostname')

                elif char == 'w':
                    # TODO: This should shorten to ~foo when applicable.
                    val = self.mem.GetVar('PWD')
                    if val.tag == value_e.Str:
                        r = val.s
                    else:
                        r = '<Error: PWD is not a string>'

                elif char == 'W':
                    val = self.mem.GetVar('PWD')
                    if val.tag == value_e.Str:
                        r = os_path.basename(val.s)
                    else:
                        r = '<Error: PWD is not a string>'

                elif char in _ONE_CHAR:
                    r = _ONE_CHAR[char]

                else:
                    r = '<\%s not implemented in $PS1> $' % char

                # See comment above on bash hack for $.
                ret.append(r.replace('$', '\\$'))

            else:
                raise AssertionError('Invalid token %r' % id_)

        return ''.join(ret)
Esempio n. 9
0
 def testBasename(self):
     self.assertEqual('bar', os_path.basename('foo/bar'))