mirror of
https://github.com/koloideal/Argenta.git
synced 2026-06-10 10:05:28 +03:00
120 lines
6.8 KiB
ReStructuredText
120 lines
6.8 KiB
ReStructuredText
.. _root_redirect_stdout:
|
||
|
||
Переопределение стандартного вывода
|
||
===================================
|
||
|
||
``Argenta`` предоставляет гибкие механизмы для форматирования вывода, включая динамические разделительные линии. Это достигается за счёт перехвата стандартного потока вывода (``stdout``), что накладывает некоторые особенности.
|
||
|
||
-----
|
||
|
||
Механизм перехвата ``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("Введите ваше имя: ")
|
||
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`` на уровне роутера. Для всех остальных команд можно оставить поведение по умолчанию.
|