Пример #1
0
def _ReconcileTypes(rval, flag_a, flag_A, span_id):
    # type: (Optional[value_t], bool, bool, int) -> value_t
    """Check that -a and -A flags are consistent with RHS.

  Special case: () is allowed to mean empty indexed array or empty assoc array
  if the context is clear.

  Shared between NewVar and Readonly.
  """
    if flag_a and rval is not None and rval.tag_() != value_e.MaybeStrArray:
        e_usage("Got -a but RHS isn't an array", span_id=span_id)

    if flag_A and rval:
        # Special case: declare -A A=() is OK.  The () is changed to mean an empty
        # associative array.
        if rval.tag_() == value_e.MaybeStrArray:
            array_val = cast(value__MaybeStrArray, rval)
            if len(array_val.strs) == 0:
                return value.AssocArray({})
                #return value.MaybeStrArray([])

        if rval.tag_() != value_e.AssocArray:
            e_usage("Got -A but RHS isn't an associative array",
                    span_id=span_id)

    return rval
Пример #2
0
 def _Value(self, arg, span_id):
     # type: (str, int) -> value_t
     if self.valid is not None and arg not in self.valid:
         e_usage('got invalid argument %r to %r, expected one of: %s' %
                 (arg, ('-' + self.name), '|'.join(self.valid)),
                 span_id=span_id)
     return value.Str(arg)
Пример #3
0
    def Run(self, cmd_val):
        # type: (cmd_value__Argv) -> int
        argv = cmd_val.argv[1:]
        attrs, arg_r = flag_spec.ParseLikeEcho('echo', cmd_val)

        arg = arg_types.echo(attrs.attrs)
        argv = arg_r.Rest()

        backslash_c = False  # \c terminates input
        arg0_spid = cmd_val.arg_spids[0]

        if arg.e:
            new_argv = []  # type: List[str]
            for a in argv:
                parts = []  # type: List[str]
                lex = match.EchoLexer(a)
                while not backslash_c:
                    id_, value = lex.Next()
                    if id_ == Id.Eol_Tok:  # Note: This is really a NUL terminator
                        break

                    tok = Token(id_, arg0_spid, value)
                    p = word_compile.EvalCStringToken(tok)

                    # Unusual behavior: '\c' prints what is there and aborts processing!
                    if p is None:
                        backslash_c = True
                        break

                    parts.append(p)

                new_argv.append(''.join(parts))
                if backslash_c:  # no more args either
                    break

            # Replace it
            argv = new_argv

        if self.exec_opts.simple_echo():
            n = len(argv)
            if n == 0:
                pass
            elif n == 1:
                self.f.write(argv[0])
            else:
                # TODO: span_id could be more accurate
                e_usage(
                    "takes at most one arg when simple_echo is on (hint: add quotes)"
                )
        else:
            #log('echo argv %s', argv)
            for i, a in enumerate(argv):
                if i != 0:
                    self.f.write(' ')  # arg separator
                self.f.write(a)

        if not arg.n and not backslash_c:
            self.f.write('\n')

        return 0
Пример #4
0
    def Run(self, cmd_val):
        # type: (cmd_value__Argv) -> int

        # There are no flags, but we need it to respect --
        _, arg_r = flag_spec.ParseCmdVal('eval', cmd_val)

        if self.exec_opts.simple_eval_builtin():
            code_str, eval_spid = arg_r.ReadRequired2('requires code string')
            if not arg_r.AtEnd():
                e_usage('requires exactly 1 argument')
        else:
            code_str = ' '.join(arg_r.Rest())
            # code_str could be EMPTY, so just use the first one
            eval_spid = cmd_val.arg_spids[0]

        line_reader = reader.StringLineReader(code_str, self.arena)
        c_parser = self.parse_ctx.MakeOshParser(line_reader)

        src = source.EvalArg(eval_spid)
        with dev.ctx_Tracer(self.tracer, 'eval', None):
            with alloc.ctx_Location(self.arena, src):
                return main_loop.Batch(self.cmd_ev,
                                       c_parser,
                                       self.arena,
                                       cmd_flags=cmd_eval.IsEvalSource)
Пример #5
0
    def Run(self, cmd_val):
        # type: (cmd_value__Argv) -> int
        attrs, arg_r = flag_spec.ParseCmdVal('hash', cmd_val)
        arg = arg_types.hash(attrs.attrs)

        rest = arg_r.Rest()
        if arg.r:
            if len(rest):
                e_usage('got extra arguments after -r')
            self.search_path.ClearCache()
            return 0

        status = 0
        if len(rest):
            for cmd in rest:  # enter in cache
                full_path = self.search_path.CachedLookup(cmd)
                if full_path is None:
                    stderr_line('hash: %r not found', cmd)
                    status = 1
        else:  # print cache
            commands = self.search_path.CachedCommands()
            commands.sort()
            for cmd in commands:
                print(cmd)

        return status
Пример #6
0
  def Run(self, cmd_val):
    # type: (cmd_value__Assign) -> int
    arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
    arg_r.Next()
    attrs = flag_spec.Parse('export_', arg_r)
    arg = arg_types.export_(attrs.attrs)
    #arg = attrs

    if arg.f:
      e_usage(
          "doesn't accept -f because it's dangerous.  "
          "(The code can usually be restructured with 'source')")

    if arg.p or len(cmd_val.pairs) == 0:
      return _PrintVariables(self.mem, cmd_val, attrs, True, builtin=_EXPORT)


    if arg.n:
      for pair in cmd_val.pairs:
        if pair.rval is not None:
          e_usage("doesn't accept RHS with -n", span_id=pair.spid)

        # NOTE: we don't care if it wasn't found, like bash.
        self.mem.ClearFlag(pair.var_name, state.ClearExport, scope_e.Dynamic)
    else:
      for pair in cmd_val.pairs:
        # NOTE: when rval is None, only flags are changed
        self.mem.SetVar(lvalue.Named(pair.var_name), pair.rval, scope_e.Dynamic,
                        flags=state.SetExport)

    return 0
    def Run(self, cmd_val):
        # type: (cmd_value__Argv) -> int
        num_args = len(cmd_val.argv) - 1
        if num_args == 0:
            # TODO: It's suppose to try another dir before doing this?
            self.errfmt.Print('pushd: no other directory')
            return 1
        elif num_args > 1:
            e_usage('got too many arguments')

        # TODO: 'cd' uses normpath?  Is that inconsistent?
        dest_dir = os_path.abspath(cmd_val.argv[1])
        try:
            posix.chdir(dest_dir)
        except OSError as e:
            self.errfmt.Print("pushd: %r: %s",
                              dest_dir,
                              posix.strerror(e.errno),
                              span_id=cmd_val.arg_spids[1])
            return 1

        self.dir_stack.Push(dest_dir)
        _PrintDirStack(self.dir_stack, SINGLE_LINE, self.mem.GetVar('HOME'))
        state.ExportGlobalString(self.mem, 'PWD', dest_dir)
        self.mem.SetPwd(dest_dir)
        return 0
Пример #8
0
    def Run(self, cmd_val):
        # type: (cmd_value__Argv) -> int

        argv = cmd_val.argv[1:]
        if len(argv) == 0:
            # umask() has a dumb API: you can't get it without modifying it first!
            # NOTE: dash disables interrupts around the two umask() calls, but that
            # shouldn't be a concern for us.  Signal handlers won't call umask().
            mask = posix.umask(0)
            posix.umask(mask)  #
            print('0%03o' % mask)  # octal format
            return 0

        if len(argv) == 1:
            a = argv[0]
            try:
                new_mask = int(a, 8)
            except ValueError:
                # NOTE: This happens if we have '8' or '9' in the input too.
                stderr_line(
                    "osh warning: umask with symbolic input isn't implemented")
                return 1
            else:
                posix.umask(new_mask)
                return 0

        e_usage('umask: unexpected arguments')
Пример #9
0
Файл: args.py Проект: o11c/oil
def ParseMore(spec, arg_r):
    # type: (flag_spec._FlagSpecAndMore, Reader) -> _Attributes
    """Return attributes and an index.

  Respects +, like set +eu

  We do NOT respect:
  
  WRONG: sh -cecho    OK: sh -c echo
  WRONG: set -opipefail     OK: set -o pipefail
  
  But we do accept these
  
  set -euo pipefail
  set -oeu pipefail
  set -oo pipefail errexit
  """
    out = _Attributes(spec.defaults)

    quit = False
    while not arg_r.AtEnd():
        arg = arg_r.Peek()
        if arg == '--':
            out.saw_double_dash = True
            arg_r.Next()
            break

        # NOTE: We don't yet support --rcfile=foo.  Only --rcfile foo.
        if arg.startswith('--'):
            try:
                action = spec.actions_long[arg]
            except KeyError:
                e_usage('got invalid flag %r' % arg, span_id=arg_r.SpanId())

            # TODO: Suffix could be 'bar' for --foo=bar
            action.OnMatch(None, None, arg_r, out)
            arg_r.Next()
            continue

        if arg.startswith('-') or arg.startswith('+'):
            char0 = arg[0]
            for ch in arg[1:]:
                #log('ch %r arg_r %s', ch, arg_r)
                try:
                    action = spec.actions_short[ch]
                except KeyError:
                    e_usage('got invalid flag %r' % ('-' + ch),
                            span_id=arg_r.SpanId())
                quit = action.OnMatch(char0, None, arg_r, out)
            arg_r.Next()  # process the next flag

            if quit:
                break
            else:
                continue

        break  # it's a regular arg

    return out
Пример #10
0
 def ReadRequired(self, error_msg):
     # type: (str) -> str
     arg = self.Peek()
     if arg is None:
         # point at argv[0]
         e_usage(error_msg, span_id=self._FirstSpanId())
     self.Next()
     return arg
Пример #11
0
def Parse(spec, arg_r):
    # type: (flag_spec._FlagSpec, Reader) -> _Attributes

    # NOTE about -:
    # 'set -' ignores it, vs set
    # 'unset -' or 'export -' seems to treat it as a variable name
    out = _Attributes(spec.defaults)

    while not arg_r.AtEnd():
        arg = arg_r.Peek()
        if arg == '--':
            out.saw_double_dash = True
            arg_r.Next()
            break

        if arg.startswith('-') and len(arg) > 1:
            n = len(arg)
            for i in xrange(1, n):  # parse flag combos like -rx
                ch = arg[i]

                if ch in spec.plus_flags:
                    out.Set(ch, value.Str('-'))
                    continue

                if ch in spec.arity0:  # e.g. read -r
                    out.SetTrue(ch)
                    continue

                if ch in spec.arity1:  # e.g. read -t1.0
                    action = spec.arity1[ch]
                    # make sure we don't pass empty string for read -t
                    attached_arg = arg[i + 1:] if i < n - 1 else None
                    action.OnMatch(attached_arg, arg_r, out)
                    break

                e_usage("doesn't accept flag %s" % ('-' + ch),
                        span_id=arg_r.SpanId())

            arg_r.Next()  # next arg

        # Only accept + if there are ANY options defined, e.g. for declare +rx.
        elif len(spec.plus_flags) and arg.startswith('+') and len(arg) > 1:
            n = len(arg)
            for i in xrange(1, n):  # parse flag combos like -rx
                ch = arg[i]
                if ch in spec.plus_flags:
                    out.Set(ch, value.Str('+'))
                    continue

                e_usage("doesn't accept option %s" % ('+' + ch),
                        span_id=arg_r.SpanId())

            arg_r.Next()  # next arg

        else:  # a regular arg
            break

    return out
Пример #12
0
 def ReadRequired2(self, error_msg):
     # type: (str) -> Tuple[str, int]
     arg = self.Peek()
     if arg is None:
         # point at argv[0]
         e_usage(error_msg, span_id=self._FirstSpanId())
     spid = self.spids[self.i]
     self.Next()
     return arg, spid
Пример #13
0
    def Run(self, cmd_val):
        # type: (cmd_value__Argv) -> int
        attrs, arg_r = flag_spec.ParseCmdVal('shopt', cmd_val)

        arg = arg_types.shopt(attrs.attrs)
        opt_names = arg_r.Rest()

        if arg.p:  # print values
            if arg.o:  # use set -o names
                self.mutable_opts.ShowOptions(opt_names)
            else:
                self.mutable_opts.ShowShoptOptions(opt_names)
            return 0

        if arg.q:  # query values
            for name in opt_names:
                index = match.MatchOption(name)
                if index == 0:
                    return 2  # bash gives 1 for invalid option; 2 is better
                if not self.mutable_opts.opt0_array[index]:
                    return 1  # at least one option is not true
            return 0  # all options are true

        if arg.s:
            b = True
        elif arg.u:
            b = False
        else:
            # If no flags are passed, print the options.  bash prints uses a
            # different format for 'shopt', but we use the same format as 'shopt
            # -p'.
            self.mutable_opts.ShowShoptOptions(opt_names)
            return 0

        if cmd_val.block:
            opt_nums = []  # type: List[int]
            for name in opt_names:
                index = match.MatchOption(name)
                if index == 0:
                    # TODO: compute span_id
                    e_usage('got invalid option %r' % name)
                opt_nums.append(index)

            with state.ctx_Option(self.mutable_opts, opt_nums, b):
                unused = self.cmd_ev.EvalBlock(cmd_val.block)
            return 0  # cd also returns 0

        # Otherwise, set options.
        for name in opt_names:
            #if arg.o:
            #  self.mutable_opts.SetOption(name, b)
            #else:
            # We allow set -o options here
            self.mutable_opts.SetShoptOption(name, b)

        return 0
Пример #14
0
  def Run(self, cmd_val):
    # type: (cmd_value__Argv) -> int
    if len(cmd_val.arg_spids) > 1:
      e_usage('got extra argument', span_id=cmd_val.arg_spids[1])

    if not _PopDirStack(self.mem, self.dir_stack, self.errfmt):
      return 1  # error

    _PrintDirStack(self.dir_stack, SINGLE_LINE, state.MaybeString(self.mem, ('HOME')))
    return 0
Пример #15
0
Файл: args.py Проект: dotmpe/oil
def _SetToArg(action, suffix, arg_r, out):
    # type: (SetToArgAction, Optional[str], Reader, _Attributes) -> bool
    """
  Perform the action.
  """
    if suffix:  # for the ',' in -d,
        arg = suffix
    else:
        arg_r.Next()
        arg = arg_r.Peek()
        if arg is None:
            e_usage('expected argument to %r' % ('-' + action.name),
                    span_id=arg_r.SpanId())

    # e.g. spec.LongFlag('--format', ['text', 'html'])
    # Should change to arg.Enum([...])
    with tagswitch(action.flag_type) as case:
        if case(flag_type_e.Enum):
            alts = cast(flag_type__Enum, action.flag_type).alts
            if arg not in alts:
                e_usage('got invalid argument %r to %r, expected one of: %s' %
                        (arg, ('-' + action.name), ', '.join(alts)),
                        span_id=arg_r.SpanId())
            val = value.Str(arg)  # type: value_t

        elif case(flag_type_e.Str):
            val = value.Str(arg)

        elif case(flag_type_e.Int):
            try:
                i = int(arg)
            except ValueError:
                e_usage('expected integer after %s, got %r' %
                        ('-' + action.name, arg),
                        span_id=arg_r.SpanId())

            # So far all our int values are > 0, so use -1 as the 'unset' value
            if i < 0:
                e_usage('got invalid integer for %s: %s' %
                        ('-' + action.name, arg),
                        span_id=arg_r.SpanId())
            val = value.Int(i)

        elif case(flag_type_e.Float):
            try:
                val = value.Float(float(arg))
            except ValueError:
                e_usage('expected number after %r, got %r' %
                        ('-' + action.name, arg),
                        span_id=arg_r.SpanId())
        else:
            raise AssertionError()

    out.Set(action.name, val)
    return action.quit_parsing_flags
Пример #16
0
    def Run(self, cmd_val):
        # type: (cmd_value__Argv) -> int
        attrs, arg_r = flag_spec.ParseOilCmdVal('forkwait', cmd_val)
        arg, span_id = arg_r.Peek2()
        if arg is not None:
            e_usage('got unexpected argument %r' % arg, span_id=span_id)

        if cmd_val.block is None:
            e_usage('expected a block')

        return self.shell_ex.RunSubshell(cmd_val.block)
Пример #17
0
    def Run(self, cmd_val):
        # type: (cmd_value__Argv) -> int
        call_spid = cmd_val.arg_spids[0]
        _, arg_r = flag_spec.ParseCmdVal('source', cmd_val)

        path = arg_r.Peek()
        if path is None:
            e_usage('missing required argument')
        arg_r.Next()

        resolved = self.search_path.Lookup(path, exec_required=False)
        if resolved is None:
            resolved = path
        try:
            f = self.fd_state.Open(resolved)  # Shell can't use descriptors 3-9
        except OSError as e:
            self.errfmt.Print_('source %r failed: %s' %
                               (path, pyutil.strerror(e)),
                               span_id=cmd_val.arg_spids[1])
            return 1

        try:
            line_reader = reader.FileLineReader(f, self.arena)
            c_parser = self.parse_ctx.MakeOshParser(line_reader)

            # A sourced module CAN have a new arguments array, but it always shares
            # the same variable scope as the caller.  The caller could be at either a
            # global or a local scope.
            source_argv = arg_r.Rest()
            self.mem.PushSource(path, source_argv)

            src = source.SourcedFile(path, call_spid)
            try:
                with alloc.ctx_Location(self.arena, src):
                    status = main_loop.Batch(self.cmd_ev,
                                             c_parser,
                                             self.arena,
                                             cmd_flags=cmd_eval.IsEvalSource)
            finally:
                self.mem.PopSource(source_argv)

            return status

        except _ControlFlow as e:
            if e.IsReturn():
                return e.StatusCode()
            else:
                raise
        finally:
            f.close()
Пример #18
0
 def _Value(self, arg, span_id):
     # type: (str, int) -> value_t
     try:
         f = float(arg)
     except ValueError:
         e_usage('expected number after %r, got %r' %
                 ('-' + self.name, arg),
                 span_id=span_id)
     # So far all our float values are > 0, so use -1.0 as the 'unset' value
     # corner case: this treats -0.0 as 0.0!
     if f < 0:
         e_usage('got invalid float for %s: %s' % ('-' + self.name, arg),
                 span_id=span_id)
     return value.Float(f)
Пример #19
0
    def OnMatch(self, attached_arg, arg_r, out):
        # type: (Optional[str], Reader, _Attributes) -> bool
        """Called when the flag matches."""
        arg_r.Next()  # always advance
        arg = arg_r.Peek()
        if arg is None:
            e_usage('Expected argument for action')

        attr_name = arg
        # Validate the option name against a list of valid names.
        if attr_name not in self.names:
            e_usage('Invalid action name %r' % arg)
        out.actions.append(attr_name)
        return False
Пример #20
0
    def _Value(self, arg, span_id):
        # type: (str, int) -> value_t
        try:
            i = int(arg)
        except ValueError:
            e_usage('expected integer after %s, got %r' %
                    ('-' + self.name, arg),
                    span_id=span_id)

        # So far all our int values are > 0, so use -1 as the 'unset' value
        # corner case: this treats -0 as 0!
        if i < 0:
            e_usage('got invalid integer for %s: %s' % ('-' + self.name, arg),
                    span_id=span_id)
        return value.Int(i)
Пример #21
0
    def OnMatch(self, attached_arg, arg_r, out):
        # type: (Optional[str], Reader, _Attributes) -> bool
        """Called when the flag matches."""
        if attached_arg is not None:  # for the ',' in -d,
            arg = attached_arg
        else:
            arg_r.Next()
            arg = arg_r.Peek()
            if arg is None:
                e_usage('expected argument to %r' % ('-' + self.name),
                        span_id=arg_r.SpanId())

        val = self._Value(arg, arg_r.SpanId())
        out.Set(self.name, val)
        return self.quit_parsing_flags
Пример #22
0
    def Run(self, cmd_val):
        # type: (cmd_value__Argv) -> int
        num_args = len(cmd_val.argv) - 1
        if num_args == 0:
            n = 1
        elif num_args == 1:
            arg = cmd_val.argv[1]
            try:
                n = int(arg)
            except ValueError:
                e_usage("Invalid shift argument %r" % arg)
        else:
            e_usage('got too many arguments')

        return self.mem.Shift(n)
Пример #23
0
    def _UnsetVar(self, arg, spid, proc_fallback):
        # type: (str, int, bool) -> bool
        """
    Returns:
      bool: whether the 'unset' builtin should succeed with code 0.
    """
        arena = self.parse_ctx.arena

        a_parser = self.parse_ctx.MakeArithParser(arg)
        arena.PushSource(source.ArgvWord(spid))
        try:
            anode = a_parser.Parse()
        except error.Parse as e:
            # show parse error
            ui.PrettyPrintError(e, arena)
            # point to word
            e_usage('Invalid unset expression', span_id=spid)
        finally:
            arena.PopSource()

        lval = self.arith_ev.EvalArithLhs(anode, spid)

        # Prevent attacks like these by default:
        #
        # unset -v 'A["$(echo K; rm *)"]'
        if not self.exec_opts.eval_unsafe_arith(
        ) and lval.tag_() != lvalue_e.Named:
            e_die(
                'Expected a variable name.  Expressions are allowed with shopt -s eval_unsafe_arith',
                span_id=spid)

        #log('lval %s', lval)
        found = False
        try:
            # not strict
            found = self.mem.Unset(lval, scope_e.Dynamic, False)
        except error.Runtime as e:
            # note: in bash, myreadonly=X fails, but declare myreadonly=X doens't
            # fail because it's a builtin.  So I guess the same is true of 'unset'.
            e.span_id = spid
            ui.PrettyPrintError(e, arena)
            return False

        if proc_fallback and not found:
            if arg in self.funcs:
                del self.funcs[arg]

        return True
    def OnMatch(self, prefix, suffix, arg_r, out):
        # type: (Optional[str], Optional[str], Reader, _Attributes) -> bool
        """Called when the flag matches."""

        if suffix:  # '0' in --verbose=0
            if suffix in ('0', 'F', 'false', 'False'):
                b = False
            elif suffix in ('1', 'T', 'true', 'Talse'):
                b = True
            else:
                e_usage('got invalid argument to boolean flag: %r' % suffix)
        else:
            b = True

        out.Set(self.name, value.Bool(b))
        return False
Пример #25
0
    def Run(self, cmd_val):
        # type: (cmd_value__Argv) -> int
        _, arg_r = flag_spec.ParseCmdVal('unalias', cmd_val)
        argv = arg_r.Rest()

        if len(argv) == 0:
            e_usage('requires an argument')

        status = 0
        for i, name in enumerate(argv):
            if name in self.aliases:
                del self.aliases[name]
            else:
                self.errfmt.Print_('No alias named %r' % name,
                                   span_id=cmd_val.arg_spids[i])
                status = 1
        return status
Пример #26
0
    def _UnsetVar(self, arg, spid, proc_fallback):
        # type: (str, int, bool) -> bool
        """
    Returns:
      bool: whether the 'unset' builtin should succeed with code 0.
    """
        arena = self.parse_ctx.arena
        a_parser = self.parse_ctx.MakeArithParser(arg)

        with alloc.ctx_Location(arena, source.ArgvWord(spid)):
            try:
                anode = a_parser.Parse()
            except error.Parse as e:
                ui.PrettyPrintError(e, arena)  # show parse error
                e_usage('Invalid unset expression', span_id=spid)

        lval = self.arith_ev.EvalArithLhs(anode, spid)

        # Prevent attacks like these by default:
        #
        # unset -v 'A["$(echo K; rm *)"]'
        if not self.exec_opts.eval_unsafe_arith(
        ) and lval.tag_() != lvalue_e.Named:
            e_usage(
                'expected a variable name.  shopt -s eval_unsafe_arith allows expressions',
                span_id=spid)

        #log('lval %s', lval)
        found = False
        try:
            # Note: This has 'setvar' semantics.  It could be 'setref' too?
            # So it composes?
            found = self.mem.Unset(lval, False)
        except error.Runtime as e:
            # note: in bash, myreadonly=X fails, but declare myreadonly=X doens't
            # fail because it's a builtin.  So I guess the same is true of 'unset'.
            e.span_id = spid
            ui.PrettyPrintError(e, arena)
            return False

        if proc_fallback and not found:
            if arg in self.funcs:
                del self.funcs[arg]

        return True
Пример #27
0
    def OnMatch(self, attached_arg, arg_r, out):
        # type: (Optional[str], Reader, _Attributes) -> bool
        """Called when the flag matches."""

        if attached_arg is not None:  # '0' in --verbose=0
            if attached_arg in ('0', 'F', 'false',
                                'False'):  # TODO: incorrect translation
                b = False
            elif attached_arg in ('1', 'T', 'true', 'Talse'):
                b = True
            else:
                e_usage('got invalid argument to boolean flag: %r' %
                        attached_arg)
        else:
            b = True

        out.Set(self.name, value.Bool(b))
        return False
Пример #28
0
  def Run(self, cmd_val):
    # type: (cmd_value__Argv) -> int
    # NOTE: This builtin doesn't do anything in non-interactive mode in bash?
    # It silently exits zero.
    # zsh -c 'history' produces an error.
    readline_mod = self.readline_mod
    if not readline_mod:
      e_usage("is disabled because Oil wasn't compiled with 'readline'")

    attrs, arg_r = flag_spec.ParseCmdVal('history', cmd_val)
    arg = arg_types.history(attrs.attrs)

    # Clear all history
    if arg.c:
      readline_mod.clear_history()
      return 0

    # Delete history entry by id number
    if arg.d >= 0:
      cmd_index = arg.d - 1

      try:
        readline_mod.remove_history_item(cmd_index)
      except ValueError:
        e_usage("couldn't find item %d" % arg.d)

      return 0

    # Returns 0 items in non-interactive mode?
    num_items = readline_mod.get_current_history_length()
    #log('len = %d', num_items)

    rest = arg_r.Rest()
    if len(rest) == 0:
      start_index = 1
    elif len(rest) == 1:
      arg0 = rest[0]
      try:
        num_to_show = int(arg0)
      except ValueError:
        e_usage('got invalid argument %r' % arg0)
      start_index = max(1, num_items + 1 - num_to_show)
    else:
      e_usage('got many arguments')

    # TODO:
    # - Exclude lines that don't parse from the history!  bash and zsh don't do
    # that.
    # - Consolidate multiline commands.

    for i in xrange(start_index, num_items+1):  # 1-based index
      item = readline_mod.get_history_item(i)
      self.f.write('%5d  %s\n' % (i, item))
    return 0
Пример #29
0
    def OnMatch(self, attached_arg, arg_r, out):
        # type: (Optional[str], Reader, _Attributes) -> bool
        """Called when the flag matches."""
        b = (attached_arg == '-')
        #log('SetNamedOption %r %r %r', prefix, suffix, arg_r)
        arg_r.Next()  # always advance
        arg = arg_r.Peek()
        if arg is None:
            # triggers on 'set -O' in addition to 'set -o' (meh OK)
            out.show_options = True
            return True  # quit parsing

        attr_name = arg
        # Validate the option name against a list of valid names.
        if attr_name not in self.names:
            e_usage('got invalid option %r' % arg, span_id=arg_r.SpanId())

        changes = out.shopt_changes if self.shopt else out.opt_changes
        changes.append((attr_name, b))
        return False
Пример #30
0
    def ParseOil(spec, arg_r):
        # type: (flag_spec._OilFlags, Reader) -> Tuple[_Attributes, int]
        out = _Attributes(spec.defaults)

        while not arg_r.AtEnd():
            arg = arg_r.Peek()
            if arg == '--':
                out.saw_double_dash = True
                arg_r.Next()
                break

            if arg == '-':  # a valid argument
                break

            # TODO: Use FLAG_RE above
            if arg.startswith('-'):
                m = libc.regex_match(_FLAG_ERE, arg)
                if m is None:
                    e_usage('Invalid flag syntax: %r' % arg)
                _, flag, val = m  # group 0 is ignored; the whole match

                # TODO: we don't need arity 1 or 0?  Booleans are like --verbose=1,
                # --verbose (equivalent to turning it on) or --verbose=0.

                name = flag.replace('-', '_')
                if name in spec.arity1:  # e.g. read -t1.0
                    action = spec.arity1[name]
                    if val.startswith('='):
                        suffix = val[1:]  # could be empty, but remove = if any
                    else:
                        suffix = None
                    action.OnMatch(suffix, arg_r, out)
                else:
                    e_usage('Unrecognized flag %r' % arg)

                arg_r.Next()  # next arg

            else:  # a regular arg
                break

        return out, arg_r.i