Exemple #1
0
    def __call__(self, argv):
        arg_r = args.Reader(argv)
        arg = INIT_COMPLETION_SPEC.Parse(arg_r)
        var_names = arg_r.Rest()  # Output variables to set
        for name in var_names:
            # Ironically we could complete these
            if name not in ['cur', 'prev', 'words', 'cword']:
                raise args.UsageError('Invalid output variable name %r' % name)
        #print(arg)

        # TODO: How does the user test a completion function programmatically?  Set
        # COMP_ARGV?
        val = self.mem.GetVar('COMP_ARGV')
        if val.tag != value_e.StrArray:
            raise args.UsageError("COMP_ARGV should be an array")
        comp_argv = val.strs

        # These are the ones from COMP_WORDBREAKS that we care about.  The rest occur
        # "outside" of words.
        break_chars = [':', '=']
        if arg.s:  # implied
            break_chars.remove('=')
        # NOTE: The syntax is -n := and not -n : -n =.
        omit_chars = arg.n or ''
        for c in omit_chars:
            if c in break_chars:
                break_chars.remove(c)

        # argv adjusted according to 'break_chars'.
        adjusted_argv = []
        for a in comp_argv:
            completion.AdjustArg(a, break_chars, adjusted_argv)

        if 'words' in var_names:
            state.SetArrayDynamic(self.mem, 'words', adjusted_argv)

        n = len(adjusted_argv)
        cur = adjusted_argv[-1]
        prev = '' if n < 2 else adjusted_argv[-2]

        if arg.s:
            if cur.startswith(
                    '--') and '=' in cur:  # Split into flag name and value
                prev, cur = cur.split('=', 1)
                split = 'true'
            else:
                split = 'false'
            # Do NOT set 'split' without -s.  Caller might not have declared it.
            # Also does not respect var_names, because we don't need it.
            state.SetStringDynamic(self.mem, 'split', split)

        if 'cur' in var_names:
            state.SetStringDynamic(self.mem, 'cur', cur)
        if 'prev' in var_names:
            state.SetStringDynamic(self.mem, 'prev', prev)
        if 'cword' in var_names:
            # Same weird invariant after adjustment
            state.SetStringDynamic(self.mem, 'cword', str(n - 1))

        return 0
Exemple #2
0
def Read(argv, splitter, mem):
    arg, i = READ_SPEC.Parse(argv)

    names = argv[i:]
    if arg.n is not None:  # read a certain number of bytes
        try:
            name = names[0]
        except IndexError:
            name = 'REPLY'  # default variable name
        s = posix.read(sys.stdin.fileno(), arg.n)
        #log('read -n: %s = %s', name, s)

        state.SetLocalString(mem, name, s)
        # NOTE: Even if we don't get n bytes back, there is no error?
        return 0

    if not names:
        names.append('REPLY')

    # leftover words assigned to the last name
    if arg.a:
        max_results = 0  # no max
    else:
        max_results = len(names)

    # We have to read more than one line if there is a line continuation (and
    # it's not -r).

    parts = []
    join_next = False
    while True:
        line = ReadLineFromStdin()
        #log('LINE %r', line)
        if not line:  # EOF
            status = 1
            break

        if line.endswith('\n'):  # strip trailing newline
            line = line[:-1]
            status = 0
        else:
            # odd bash behavior: fail even if we can set variables.
            status = 1

        spans = splitter.SplitForRead(line, not arg.r)
        done, join_next = _AppendParts(line, spans, max_results, join_next,
                                       parts)

        #log('PARTS %s continued %s', parts, continued)
        if done:
            break

    if arg.a:
        state.SetArrayDynamic(mem, arg.a, parts)
    else:
        for i in xrange(max_results):
            try:
                s = parts[i]
            except IndexError:
                s = ''  # if there are too many variables
            #log('read: %s = %s', names[i], s)
            state.SetStringDynamic(mem, names[i], s)

    return status
Exemple #3
0
    def __call__(self, arg_vec):
        arg, i = READ_SPEC.ParseVec(arg_vec)

        names = arg_vec.strs[i:]
        if arg.n is not None:  # read a certain number of bytes
            stdin = sys.stdin.fileno()
            try:
                name = names[0]
            except IndexError:
                name = 'REPLY'  # default variable name
            s = ""
            if sys.stdin.isatty():  # set stdin to read in unbuffered mode
                orig_attrs = termios.tcgetattr(stdin)
                attrs = termios.tcgetattr(stdin)
                # disable canonical (buffered) mode
                # see `man termios` for an extended discussion
                attrs[3] &= ~termios.ICANON
                try:
                    termios.tcsetattr(stdin, termios.TCSANOW, attrs)
                    # posix.read always returns a single character in unbuffered mode
                    while arg.n > 0:
                        s += posix.read(stdin, 1)
                        arg.n -= 1
                finally:
                    termios.tcsetattr(stdin, termios.TCSANOW, orig_attrs)
            else:
                s_len = 0
                while arg.n > 0:
                    buf = posix.read(stdin, arg.n)
                    # EOF
                    if buf == '':
                        break
                    arg.n -= len(buf)
                    s += buf

            state.SetLocalString(self.mem, name, s)
            # NOTE: Even if we don't get n bytes back, there is no error?
            return 0

        if not names:
            names.append('REPLY')

        # leftover words assigned to the last name
        if arg.a:
            max_results = 0  # no max
        else:
            max_results = len(names)

        # We have to read more than one line if there is a line continuation (and
        # it's not -r).

        parts = []
        join_next = False
        while True:
            line = ReadLineFromStdin()
            #log('LINE %r', line)
            if not line:  # EOF
                status = 1
                break

            if line.endswith('\n'):  # strip trailing newline
                line = line[:-1]
                status = 0
            else:
                # odd bash behavior: fail even if we can set variables.
                status = 1

            spans = self.splitter.SplitForRead(line, not arg.r)
            done, join_next = _AppendParts(line, spans, max_results, join_next,
                                           parts)

            #log('PARTS %s continued %s', parts, continued)
            if done:
                break

        if arg.a:
            state.SetArrayDynamic(self.mem, arg.a, parts)
        else:
            for i in xrange(max_results):
                try:
                    s = parts[i]
                except IndexError:
                    s = ''  # if there are too many variables
                #log('read: %s = %s', names[i], s)
                state.SetStringDynamic(self.mem, names[i], s)

        return status