123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- from __future__ import annotations
- import sys
- from typing import TextIO, cast
- from prompt_toolkit.utils import (
- get_bell_environment_variable,
- get_term_environment_variable,
- is_conemu_ansi,
- )
- from .base import DummyOutput, Output
- from .color_depth import ColorDepth
- from .plain_text import PlainTextOutput
- __all__ = [
- "create_output",
- ]
- def create_output(
- stdout: TextIO | None = None, always_prefer_tty: bool = False
- ) -> Output:
- """
- Return an :class:`~prompt_toolkit.output.Output` instance for the command
- line.
- :param stdout: The stdout object
- :param always_prefer_tty: When set, look for `sys.stderr` if `sys.stdout`
- is not a TTY. Useful if `sys.stdout` is redirected to a file, but we
- still want user input and output on the terminal.
- By default, this is `False`. If `sys.stdout` is not a terminal (maybe
- it's redirected to a file), then a `PlainTextOutput` will be returned.
- That way, tools like `print_formatted_text` will write plain text into
- that file.
- """
- # Consider TERM, PROMPT_TOOLKIT_BELL, and PROMPT_TOOLKIT_COLOR_DEPTH
- # environment variables. Notice that PROMPT_TOOLKIT_COLOR_DEPTH value is
- # the default that's used if the Application doesn't override it.
- term_from_env = get_term_environment_variable()
- bell_from_env = get_bell_environment_variable()
- color_depth_from_env = ColorDepth.from_env()
- if stdout is None:
- # By default, render to stdout. If the output is piped somewhere else,
- # render to stderr.
- stdout = sys.stdout
- if always_prefer_tty:
- for io in [sys.stdout, sys.stderr]:
- if io is not None and io.isatty():
- # (This is `None` when using `pythonw.exe` on Windows.)
- stdout = io
- break
- # If the output is still `None`, use a DummyOutput.
- # This happens for instance on Windows, when running the application under
- # `pythonw.exe`. In that case, there won't be a terminal Window, and
- # stdin/stdout/stderr are `None`.
- if stdout is None:
- return DummyOutput()
- # If the patch_stdout context manager has been used, then sys.stdout is
- # replaced by this proxy. For prompt_toolkit applications, we want to use
- # the real stdout.
- from prompt_toolkit.patch_stdout import StdoutProxy
- while isinstance(stdout, StdoutProxy):
- stdout = stdout.original_stdout
- if sys.platform == "win32":
- from .conemu import ConEmuOutput
- from .win32 import Win32Output
- from .windows10 import Windows10_Output, is_win_vt100_enabled
- if is_win_vt100_enabled():
- return cast(
- Output,
- Windows10_Output(stdout, default_color_depth=color_depth_from_env),
- )
- if is_conemu_ansi():
- return cast(
- Output, ConEmuOutput(stdout, default_color_depth=color_depth_from_env)
- )
- else:
- return Win32Output(stdout, default_color_depth=color_depth_from_env)
- else:
- from .vt100 import Vt100_Output
- # Stdout is not a TTY? Render as plain text.
- # This is mostly useful if stdout is redirected to a file, and
- # `print_formatted_text` is used.
- if not stdout.isatty():
- return PlainTextOutput(stdout)
- return Vt100_Output.from_pty(
- stdout,
- term=term_from_env,
- default_color_depth=color_depth_from_env,
- enable_bell=bell_from_env,
- )
|