예제 #1
0
def magictype(text, prompt_template="default", speed=1):
    """Echo each character in ``text`` as keyboard characters are pressed.
    Characters are echo'd ``speed`` characters at a time.
    """
    echo_prompt(prompt_template)
    cursor_position = 0
    with raw_mode():
        while True:
            char = text[cursor_position:cursor_position + speed]
            in_char = getchar()
            if in_char in {ESC, CTRLC}:
                echo(carriage_return=True)
                raise click.Abort()
            elif in_char == BACKSPACE:
                if cursor_position > 0:
                    echo("\b \b", nl=False)
                    cursor_position -= 1
            elif in_char in RETURNS:
                # Only return at end of command
                if cursor_position >= len(text):
                    echo("\r", nl=True)
                    break
            elif in_char == CTRLZ and hasattr(signal, "SIGTSTP"):
                # Background process
                os.kill(0, signal.SIGTSTP)
                # When doitlive is back in foreground, clear the terminal
                # and resume where we left off
                click.clear()
                echo_prompt(prompt_template)
                echo(text[:cursor_position], nl=False)
            else:
                if cursor_position < len(text):
                    echo(char, nl=False)
                    increment = min([speed, len(text) - cursor_position])
                    cursor_position += increment
예제 #2
0
 def run_commands(self):
     """Automatically type and execute all commands."""
     more = 0
     prompt = sys.ps1
     for command in self.commands:
         try:
             prompt = sys.ps2 if more else sys.ps1
             try:
                 magictype(command,
                           prompt_template=prompt,
                           speed=self.speed)
             except EOFError:
                 self.write("\n")
                 break
             else:
                 if command.strip() == "exit()":
                     return
                 more = self.push(command)
         except KeyboardInterrupt:
             self.write("\nKeyboardInterrupt\n")
             self.resetbuffer()
             more = 0
             sys.exit(1)
     echo_prompt(prompt)
     wait_for(RETURNS)
예제 #3
0
def regulartype(prompt_template="default"):
    """Echo each character typed. Unlike magictype, this echos the characters the
    user is pressing.

    Returns: command_string |  The command to be passed to the shell to run. This is
                            |  typed by the user.
    """
    echo_prompt(prompt_template)
    command_string = ""
    cursor_position = 0
    with raw_mode():
        while True:
            in_char = getchar()
            if in_char in {ESC, CTRLC}:
                echo(carriage_return=True)
                raise click.Abort()
            elif in_char == TAB:
                echo("\r", nl=True)
                return in_char
            elif in_char == BACKSPACE:
                if cursor_position > 0:
                    echo("\b \b", nl=False)
                    command_string = command_string[:-1]
                    cursor_position -= 1
            elif in_char in RETURNS:
                echo("\r", nl=True)
                return command_string
            elif in_char == CTRLZ and hasattr(signal, "SIGTSTP"):
                # Background process
                os.kill(0, signal.SIGTSTP)
                # When doitlive is back in foreground, clear the terminal
                # and resume where we left off
                click.clear()
                echo_prompt(prompt_template)
            else:
                echo(in_char, nl=False)
                command_string += in_char
                cursor_position += 1
예제 #4
0
파일: cli.py 프로젝트: x0rzkov/doitlive
def run(
    commands,
    shell=None,
    prompt_template="default",
    speed=1,
    quiet=False,
    test_mode=False,
    commentecho=False,
):
    """Main function for "magic-running" a list of commands."""
    if not quiet:
        secho("We'll do it live!", fg="red", bold=True)
        secho(
            "STARTING SESSION: Press Ctrl-C at any time to exit.",
            fg="yellow",
            bold=True,
        )
        click.pause()

    click.clear()
    state = SessionState(
        shell=shell,
        prompt_template=prompt_template,
        speed=speed,
        test_mode=test_mode,
        commentecho=commentecho,
    )

    i = 0
    while i < len(commands):
        command = commands[i].strip()
        i += 1
        if not command:
            continue
        is_comment = command.startswith("#")
        if not is_comment:
            command_as_list = shlex.split(ensure_utf8(command))
        else:
            command_as_list = None
        shell_match = SHELL_RE.match(command)
        if is_comment:
            # Parse comment magic
            match = OPTION_RE.match(command)
            if match:
                option, arg = match.group("option"), match.group("arg")
                func = OPTION_MAP[option]
                func(state, arg)
            elif state.commentecho():
                comment = command.lstrip("#")
                secho(comment, fg="yellow", bold=True)
            continue
        # Handle 'export' and 'alias' commands by storing them in SessionState
        elif command_as_list and command_as_list[0] in ["alias", "export"]:
            magictype(command,
                      prompt_template=state["prompt_template"],
                      speed=state["speed"])
            # Store the raw commands instead of using add_envvar and add_alias
            # to avoid having to parse the command ourselves
            state.add_command(command)
        # Handle ```python and ```ipython by running "player" consoles
        elif shell_match:
            shell_name = shell_match.groups()[0].strip()
            py_commands = []
            more = True
            while more:  # slurp up all the python code
                try:
                    py_command = commands[i].rstrip()
                except IndexError:
                    raise SessionError("Unmatched {0} code block in "
                                       "session file.".format(shell_name))
                i += 1
                if py_command.startswith("```"):
                    i += 1
                    more = False
                else:
                    py_commands.append(py_command)
            # Run the player console
            magictype(
                shell_name,
                prompt_template=state["prompt_template"],
                speed=state["speed"],
            )

            if shell_name == "ipython":
                try:
                    from doitlive.ipython_consoles import start_ipython_player
                except ImportError:
                    raise RuntimeError(
                        "```ipython blocks require IPython to be installed")
                # dedent all the commands to account for IPython's autoindentation
                ipy_commands = [textwrap.dedent(cmd) for cmd in py_commands]
                start_ipython_player(ipy_commands, speed=state["speed"])
            else:
                start_python_player(py_commands, speed=state["speed"])
        else:
            # goto_stealthmode determines when to switch to stealthmode
            goto_stealthmode = magicrun(command, **state)
            # stealthmode allows user to type live commands outside of automated script
            i -= stealthmode(state, goto_stealthmode)
    echo_prompt(state["prompt_template"])
    wait_for(RETURNS)
    if not quiet:
        secho("FINISHED SESSION", fg="yellow", bold=True)
예제 #5
0
def run(commands, shell=None, prompt_template='default', speed=1,
        quiet=False, test_mode=False, commentecho=False):
    """Main function for "magic-running" a list of commands."""
    if not quiet:
        secho("We'll do it live!", fg='red', bold=True)
        secho('STARTING SESSION: Press Ctrl-C at any time to exit.',
              fg='yellow', bold=True)
        click.pause()

    click.clear()
    state = SessionState(shell=shell, prompt_template=prompt_template,
                         speed=speed, test_mode=test_mode,
                         commentecho=commentecho)

    i = 0
    while i < len(commands):
        command = commands[i].strip()
        command_as_list = shlex.split(ensure_utf8(command))
        i += 1
        if not command:
            continue
        shell_match = SHELL_RE.match(command)
        if command.startswith('#'):
            # Parse comment magic
            match = OPTION_RE.match(command)
            if match:
                option, arg = match.group('option'), match.group('arg')
                func = OPTION_MAP[option]
                func(state, arg)
            elif state.commentecho():
                comment = command.lstrip("#")
                secho(comment, fg='yellow', bold=True)
            continue
        # Handle 'export' and 'alias' commands by storing them in SessionState
        elif command_as_list and command_as_list[0] in ['alias', 'export']:
            magictype(command,
                      prompt_template=state['prompt_template'],
                      speed=state['speed'])
            # Store the raw commands instead of using add_envvar and add_alias
            # to avoid having to parse the command ourselves
            state.add_command(command)
        # Handle ```python and ```ipython by running "player" consoles
        elif shell_match:
            shell_name = shell_match.groups()[0].strip()
            py_commands = []
            more = True
            while more:  # slurp up all the python code
                try:
                    py_command = commands[i].rstrip()
                except IndexError:
                    raise SessionError('Unmatched {0} code block in '
                                       'session file.'.format(shell_name))
                i += 1
                if py_command.startswith('```'):
                    i += 1
                    more = False
                else:
                    py_commands.append(py_command)
            # Run the player console
            magictype(shell_name,
                      prompt_template=state['prompt_template'],
                      speed=state['speed'])
            if shell_name == 'ipython':
                try:
                    from doitlive.ipython_consoles import start_ipython_player
                except ImportError:
                    raise RuntimeError('```ipython blocks require IPython to be installed')
                # dedent all the commands to account for IPython's autoindentation
                ipy_commands = [textwrap.dedent(cmd) for cmd in py_commands]
                start_ipython_player(ipy_commands, speed=state['speed'])
            else:
                start_python_player(py_commands, speed=state['speed'])
        else:
            magicrun(command, **state)
    echo_prompt(state['prompt_template'])
    wait_for(RETURNS)
    if not quiet:
        secho("FINISHED SESSION", fg='yellow', bold=True)