예제 #1
0
def choose_config(config: Any) -> Any:
    """Chooses a random value from a list of config options or returns the config if it is not in a list."""
    if isinstance(config, list):
        choice = random.choice(config)
        CONSOLE.print(f"[blue]Chose {choice}.[/blue]")
        return choice
    return config
예제 #2
0
    def run_file(self, file: str) -> Union[tuple, str]:
        """Send code form file to the api and return the response."""
        args = helpers.get_args()
        stdin = helpers.get_stdin()

        try:
            with open(file, "r", encoding="utf-8") as f:
                code = f.read()

            if not any(file.endswith("." + ext) for ext in self.extensions):
                CONSOLE.print("File Extension language is not supported!",
                              style="bold red")
                helpers.close()

        except FileNotFoundError:
            CONSOLE.print("Path is invalid; File not found", style="bold red")
            helpers.close()

        language = self.extensions[file[file.rfind(".") + 1:]]

        payload = PistonQuery(
            language=language,
            code=code,
            args=args,
            stdin=stdin,
        )

        data = services.query_piston(CONSOLE, payload)

        if len(data["output"]) == 0:
            return "Your code ran without output.", language

        return data["output"].split("\n"), language
예제 #3
0
    def ask_input(self, theme: str) -> Union[tuple, str]:
        """
        Make a multiline prompt for code input and send the code to the api.

        The compiled output from the api is returned.
        """
        language = helpers.get_lang()
        args = helpers.get_args()
        stdin = helpers.get_stdin()

        CONSOLE.print(
            "[green]Enter your code, (press esc + enter to run)[/green]")
        style = helpers.set_style(theme)

        CONSOLE.print()
        code = prompt(
            "",
            lexer=PygmentsLexer(lexers_dict[language]),
            include_default_pygments_style=False,
            style=style,
            multiline=True,
        )
        payload = PistonQuery(language=language,
                              args=args,
                              stdin=stdin,
                              code=code)

        data = services.query_piston(CONSOLE, payload)

        if len(data["output"]) == 0:
            return "Your code ran without output.", language

        return data["output"].split("\n"), language
예제 #4
0
 def fix_prompt(self) -> str:
     """Fixes the prompt_start configuration variables."""
     if self.validate_prompt():
         return choose_config(self.prompt)
     CONSOLE.print(
         f"[red]Prompt start invalid. {repr(self.prompt)} contains a new"
         "line character. Using default prompt start instead.[/red]")
     return self.default_prompt
예제 #5
0
 def check_box_exists(box: str) -> bool:
     """Ensures that a given box style exists."""
     if box not in BOX_STYLES:
         CONSOLE.print(
             f'[red]Box Style invalid, "{box}" not recognized. Using default box style.[/red]'
         )
         return False
     return True
예제 #6
0
 def check_theme_exists(theme: str) -> bool:
     """Ensures that a given theme exists."""
     if theme not in themes:
         CONSOLE.print(
             f'[red]Theme invalid, "{theme}" not recognized. Using default theme.[/red]'
         )
         return False
     return True
예제 #7
0
    def set_language(self, language: str) -> None:
        """
        Set the language to the option passed by use.

        If language is not supported then exit the CLI.
        """
        if language not in languages_:
            CONSOLE.print("[bold red]Language is not supported![/bold red]")
            helpers.close()

        self.language = language
예제 #8
0
def theme_list() -> None:
    """List all available themes with a short code snippet."""
    for theme in themes:
        CONSOLE.print(f"[bold red underline]Theme {theme}: [/bold red underline]\n")
        try:
            style = get_style_by_name(theme)
        except ClassNotFound:
            style = scheme_dict[theme]
        finally:
            print(
                highlight(
                    THEME_PREVIEW, Python3Lexer(), Terminal256Formatter(style=style)
                )
            )
예제 #9
0
    def get_code() -> Union[bool, str]:
        """Prompt the user for the pastebin link."""
        link = CONSOLE.input("[green]Enter the link:[/green] ").lower()

        base_url = urllib.parse.quote_plus(
            link.split(" ")[-1][5:].strip("/"), safe=";/?:@&=$,><-[]"
        )

        domain = base_url.split("/")[2]
        if domain == "paste.pythondiscord.com":
            if "/raw/" in base_url:
                url = base_url
            token = base_url.split("/")[-1]
            if "." in token:
                token = token[: token.rfind(".")]  # removes extension
            url = f"https://paste.pythondiscord.com/raw/{token}"
        else:
            CONSOLE.print(
                "[red]Can only accept links from paste.pythondiscord.com.[/red]"
            )
            return False

        response = requests.get(url)
        if response.status_code == 404:
            CONSOLE.print("[red]Nothing found. Check your link[/red]")
            return False
        elif response.status_code != 200:
            CONSOLE.print(
                f"[red]An error occurred (status code: {response.status_code}).[/red]"
            )
            return False
        return response.text
예제 #10
0
    def validate_type(self) -> bool:
        """Validates the type of a given configuration."""
        if self.current_type is not self.target_type and self.current_type is not list:
            CONSOLE.print(
                f'[red]Configuration "{self.config.__name__}" invalid, use type {self.target_type.__name__}, '
                f"not {self.current_type.__name__}. Using default setting.[/red]"
            )
            return False

        if self.current_type is list:
            for item in self.config:
                if not isinstance(item, self.target_type):
                    CONSOLE.print(
                        f'[red]A possible "{item}" in the list of "{self.name}" configurations '
                        f"specified has an invalid type, use type {self.target_type.__name__}. "
                        f"not {type(item).__name__}. Using default setting.[/red]"
                    )
                    return False

            CONSOLE.print(
                f'[blue]A list of possible configurations was found for the "{self.name}" option. '
                "Choosing a random one.")

        return True
예제 #11
0
    def run_shell(self, language: str, theme: str, prompt_start: str,
                  prompt_continuation: str) -> None:
        """Run the shell."""
        CONSOLE.print(
            "[bold blue]NOTE: stdin and args will be prompted after code. "
            "Use escape + enter to finish writing the code. "
            "To quit, use ctrl + c. [/bold blue]")

        self.set_language(language)
        self.set_prompt_session(prompt_start, prompt_continuation)
        self.style = helpers.set_style(theme)

        while True:
            query = self.prompt()

            data = services.query_piston(CONSOLE, query)

            if len(data["output"]) == 0:
                CONSOLE.print("Your code ran without output.")
            else:
                CONSOLE.print("\n".join([
                    f"{i:02d} | {line}"
                    for i, line in enumerate(data["output"].split("\n"), 1)
                ]))
예제 #12
0
def main() -> None:
    """Implement the main piston-cli process."""
    args = commands_dict["base"]()

    if args.version:
        print(version.__version__, flush=True)
        helpers.close()

    if args.list:
        list_commands = {
            "themes": commands_dict["theme_list"],
            "languages": ("Languages", grouper(languages_, 2)),
            "boxes": ("Box Styles", grouper(BOX_STYLES, 2)),
        }
        try:
            # If the value is an tuple i.e. it is formatted for a box.
            if isinstance(list_commands[args.list], tuple):
                table = make_table(*list_commands[args.list])
                CONSOLE.print(table)
            else:
                # Else it is just a callable and we can call it.
                list_commands[args.list]()
        except KeyError:
            CONSOLE.print(
                f"[red] Invalid option provided - Valid "
                f"options include:[/red] [cyan]{', '.join(list_commands.keys())}[/cyan]"
            )

        helpers.close()

    config_loader = ConfigLoader(args.config)
    config = config_loader.load_config()
    output = None
    init_lexers()

    if args.theme:
        CONSOLE.print(
            f"[indian_red]- Theme flag specified, overwriting theme loaded from "
            f"config: {args.theme}[/indian_red]")

    if args.file:
        output, language = commands_dict["from_file"](args.file)

    elif args.pastebin:
        output, language = commands_dict["from_link"]()

    elif args.shell:
        try:
            commands_dict["from_shell"](
                args.shell,
                args.theme or config["theme"],
                config["prompt_start"],
                config["prompt_continuation"],
            )
        except KeyboardInterrupt:
            pass

    else:
        output, language = commands_dict["from_input"](args.theme
                                                       or config["theme"])

    if output:
        CONSOLE.print(f"\nHere is your {language} output:")
        CONSOLE.print(
            helpers.print_msg_box(
                output,
                style=config["box_style"],
            ))
        helpers.close()