.. _root_redirect_stdout:

Переопределение стандартного вывода
===================================

``Argenta`` предоставляет гибкие механизмы для форматирования вывода, включая динамические разделительные линии. Это достигается за счёт перехвата стандартного потока вывода (``stdout``), что накладывает некоторые особенности.

-----

Когда нужно отключать перехват stdout
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Отключайте перехват ``stdout`` (``disable_redirect_stdout=True`` в ``Router``), если ваши команды:

✓ Используют ``input()`` для интерактивного ввода данных от пользователя 

✓ Используют прогресс-бары (``tqdm``, ``rich.progress``) 

✓ Выводят данные в реальном времени (streaming, логи) 

✓ Используют библиотеки, которые напрямую работают с ``stdout`` 

Для обычных команд с ``print()`` перехват можно оставить включённым — это не влияет на их работу.

-----

Механизм перехвата ``stdout``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

По умолчанию ``Argenta`` перехватывает весь текст, выводимый в ``stdout`` внутри обработчика команды. Это необходимо для реализации **динамических разделителей**: система анализирует вывод, находит самую длинную строку и использует её для отрисовки верхней и нижней границ. Такой подход создаёт аккуратный интерфейс, где вывод команды «обёрнут» в рамку, подогнанную под его содержимое.

Пример приложения с динамической разделительной линией:

.. image:: https://i.ibb.co/yn9rWnNC/2025-11-07-180751.png
  :alt: Example of an application with a dynamic dividing line

Как вы можете заметить, разделительная линия ровно той же длины, что и самая длинная строка в выводе.

То же приложение с статической линией:

.. image:: https://i.ibb.co/P8B4xyp/2025-11-07-180330.png
  :alt: Example of an application with a static dividing line

В этом примере разделительная линия имеет фиксированную длину (по умолчанию 25 символов).

-----

Побочные эффекты перехвата ``stdout``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Побочный эффект этого механизма проявляется при использовании функций, которые последовательно выводят текст в консоль и ожидают ввод от пользователя. Классический пример — стандартная функция ``input()``.

.. code-block:: python
    :linenos:

    user_name = input("Enter your name: ")
    print(f"Привет, {user_name}!")

.. warning::
   При включённом перехвате ``stdout`` текст (например, ``"Введите ваше имя: "``) **не будет выведен в консоль немедленно**. Он попадёт в буфер и отобразится лишь после завершения работы обработчика вместе с остальным выводом. Это может сбить пользователя с толку.

-----

Отключение перехвата ``stdout`` с помощью ``disable_redirect_stdout``
---------------------------------------------------------------------

Чтобы решить эту проблему, в конструкторе ``Router`` предусмотрен специальный аргумент:

*   **disable_redirect_stdout** (``bool``, по умолчанию ``False``)

Если при создании роутера установить ``disable_redirect_stdout=True``, механизм перехвата ``stdout`` будет отключён для всех его обработчиков.

**Пример использования:**

.. literalinclude:: ../code_snippets/redirect_stdout/sample.py
   :language: python
   :linenos:

В этом случае ``input()`` будет работать как обычно, и пользователь сразу увидит приглашение к вводу.

-----

Типы разделительных линий
--------------------------

``Argenta`` поддерживает два типа разделителей, которые настраиваются при инициализации ``App``:

1.  **``DynamicDividingLine()``**
	*  Поведение по умолчанию. Длина линии динамически подстраивается под самый длинный текст в выводе.
	*  Требует включённого перехвата ``stdout`` (``disable_redirect_stdout=False`` в роутере).

2.  **``StaticDividingLine(length: int = 25)``**
	*  Линия имеет фиксированную длину (по умолчанию 25 символов), которую можно задать через аргумент ``length``.
	*  Используется принудительно для роутеров с ``disable_redirect_stdout=True``, так как без перехвата вывода невозможно определить динамическую длину.

-----

Настройка разделительной линии в ``App``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Вы можете глобально задать тип разделителя для всего приложения через аргумент ``dividing_line`` в конструкторе ``App``.

**Пример использования:**

.. literalinclude:: ../code_snippets/redirect_stdout/sample2.py
   :language: python
   :linenos:

-----

Итоговое поведение
------------------

.. list-table::
   :widths: 25 25 35 15
   :header-rows: 1

   * - ``disable_redirect_stdout`` на ``Router``
     - Тип линии в ``App``
     - Фактическое поведение
     - ``input()`` работает корректно?
   * - ``False`` (по умолчанию)
     - ``DynamicDividingLine``
     - Динамическая линия, длина по содержимому
     - Нет
   * - ``False`` (по умолчанию)
     - ``StaticDividingLine``
     - Статическая линия указанной длины
     - Нет
   * - ``True``
     - ``DynamicDividingLine``
     - **Принудительно статическая линия** (длина по умолч.)
     - Да
   * - ``True``
     - ``StaticDividingLine``
     - Статическая линия указанной длины
     - Да

Таким образом, для интерактивных команд, требующих ввода от пользователя, отключайте перехват ``stdout`` на уровне роутера. Для всех остальных команд можно оставить поведение по умолчанию.
