예제 #1
0
    def _write_prompt(self, io: IO) -> None:
        """
        Outputs the question prompt.
        """
        message = self._question

        io.write_error("<question>{}</question> ".format(message))
예제 #2
0
    def _write_prompt(self, io: IO) -> None:
        message = self._question

        message = "<question>{} (yes/no)</> [<comment>{}</>] ".format(
            message, "yes" if self._default else "no"
        )

        io.write_error(message)
예제 #3
0
    def _write_prompt(self, io: IO) -> None:
        """
        Outputs the question prompt.
        """
        message = self._question
        default = self._default

        if default is None:
            message = "<question>{}</question>: ".format(message)
        elif self._multi_select:
            choices = self._choices
            default = default.split(",")

            for i, value in enumerate(default):
                default[i] = choices[int(value.strip())]

            message = "<question>{}</question> [<comment>{}</comment>]:".format(
                message, ", ".join(default))
        else:
            choices = self._choices
            message = "<question>{}</question> [<comment>{}</comment>]:".format(
                message, choices[int(default)])

        if len(self._choices) > 1:
            width = max(
                *map(len, [str(k) for k, _ in enumerate(self._choices)]))
        else:
            width = 1

        messages = [message]
        for key, value in enumerate(self._choices):
            messages.append(" [<comment>{:{}}</>] {}".format(
                key, width, value))

        io.write_error_line("\n".join(messages))

        message = self._prompt

        io.write_error(message)
예제 #4
0
    def _autocomplete(self, io: IO) -> str:
        """
        Autocomplete a question.
        """
        autocomplete = self._autocomplete_values

        ret = ""

        i = 0
        ofs = -1
        matches = [x for x in autocomplete]
        num_matches = len(matches)

        stty_mode = subprocess.check_output(["stty",
                                             "-g"]).decode().rstrip("\n")

        # Disable icanon (so we can read each keypress) and echo (we'll do echoing here instead)
        subprocess.check_output(["stty", "-icanon", "-echo"])

        # Add highlighted text style
        style = Style(options=["reverse"])
        io.error_output.formatter.set_style("hl", style)

        # Read a keypress
        while True:
            c = io.read(1)

            # Backspace character
            if c == "\177":
                if num_matches == 0 and i != 0:
                    i -= 1
                    # Move cursor backwards
                    io.write_error("\033[1D")

                if i == 0:
                    ofs = -1
                    matches = [x for x in autocomplete]
                    num_matches = len(matches)
                else:
                    num_matches = 0

                # Pop the last character off the end of our string
                ret = ret[:i]
            # Did we read an escape sequence
            elif c == "\033":
                c += io.read(2)

                # A = Up Arrow. B = Down Arrow
                if c[2] == "A" or c[2] == "B":
                    if c[2] == "A" and ofs == -1:
                        ofs = 0

                    if num_matches == 0:
                        continue

                    ofs += -1 if c[2] == "A" else 1
                    ofs = (num_matches + ofs) % num_matches
            elif ord(c) < 32:
                if c == "\t" or c == "\n":
                    if num_matches > 0 and ofs != -1:
                        ret = matches[ofs]
                        # Echo out remaining chars for current match
                        io.write_error(ret[i:])
                        i = len(ret)

                    if c == "\n":
                        io.write_error(c)
                        break

                    num_matches = 0

                continue
            else:
                io.write_error(c)
                ret += c
                i += 1

                num_matches = 0
                ofs = 0

                for value in autocomplete:
                    # If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
                    if value.startswith(ret) and i != len(value):
                        num_matches += 1
                        matches[num_matches - 1] = value

            # Erase characters from cursor to end of line
            io.write_error("\033[K")

            if num_matches > 0 and ofs != -1:
                # Save cursor position
                io.write_error("\0337")
                # Write highlighted text
                io.write_error("<hl>" + matches[ofs][i:] + "</hl>")
                # Restore cursor position
                io.write_error("\0338")

        subprocess.call(["stty", "{}".format(stty_mode)])

        return ret