================= Quick-Start Guide ================= Welcome to the quick-start guide! (Well, it's more of a formal documentation) We will go through and explain each element of ``framed_text``, from simple frames to complex data structures and progress bars! More specifically, this guide will cover: - ``framed_text.FramedText`` - ``framed_text.LabeledData`` - ``framed_text.Status`` - ``framed_text.FramedHeader`` - ``framed_text.ShortenText`` - ``framed_text.ProgressBar`` - ``framed_text.Spinner`` .. important:: Make sure to import the module first! .. code-block:: python3 :linenos: from framed_text import FramedText, LabeledData, Status, ... # Any other items you need Adding Frames around Text ------------------------- The basic parameters for ``FramedText`` include: - ``framed_color``: The color of the frame - ``title``: The title of the frame - ``title_color``: The color of the title - ``attrs``: The attributes of the title - ``text``: The text to display We'll go over each of these parameters in detail. Creating a Simple Frame with Text ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can create a simple frame using the following code: .. code-block:: python3 :caption: Using the ``FramedText`` class :linenos: ft: FramedText = FramedText( text=[ "Hello world" ] ) print(ft) .. image:: _static/imgs/quickstart_1.png We can add more text by adding more strings to the ``text`` list: .. code-block:: python3 :caption: Multiple lines can be added to the ``text`` list :linenos: ft: FramedText = FramedText( text=[ "Hello world", "Another line", "Another Another line" ] ) print(ft) .. image:: _static/imgs/quickstart_2.png Styling the Frame and Adding a Title ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can color the frame using the ``framed_color`` parameter: .. code-block:: python3 :caption: Coloring the frame red :linenos: ft: FramedText = FramedText( frame_color="red", text=[ "Hello world" ] ) print(ft) .. image:: _static/imgs/quickstart_5.png You can add a title to the frame using the ``title`` parameter: .. code-block:: python3 :caption: A simple title for the frame :linenos: ft: FramedText = FramedText( title="This is a title", frame_color="red", text=[ "Hello world" ] ) print(ft) .. image:: _static/imgs/quickstart_6.png To color the title, use ``title_color``: .. code-block:: python3 :caption: Coloring the title green. Note that the frame color is still red. :linenos: ft: FramedText = FramedText( title="This is a title", frame_color="red", title_color="green", text=[ "Hello world" ] ) print(ft) .. image:: _static/imgs/quickstart_7.png The title supports termcolor's formatting options using ``attrs`` parameter: .. code-block:: python3 :caption: Applying a bold and underline style to the title. The title color is still green. :linenos: ft: FramedText = FramedText( title="This is a title", frame_color="red", title_color="green", attrs=["bold", "underline"], text=[ "Hello world" ] ) print(ft) .. image:: _static/imgs/quickstart_8.png Advanced Parameters ~~~~~~~~~~~~~~~~~~~ In addition to the above parameters, ``FramedText`` also features: - ``cutoff``: If true, will cut off text if it exceeds the terminal width - ``mode``: Determines how text is cut off. Used with ``cutoff`` - ``allow_ansi``: If true, will allow ANSI codes to be displayed. By default, this is false for reasons we'll get to. - ``center_text``: If true, will center the ``text`` display to the middle of the frame. .. versionadded:: 2026.06.03.18.00 - ``frame_size``: Determines how the frame is rendered. See `frame_size`_ for more information. mode ```` .. versionchanged:: 2026.05.04.17.15 ``mode`` now applies to all ``str`` objects in the ``text`` parameter, not just ``LabeledData`` and ``Status`` objects. ``mode`` can be one of the following: - ``"char"``: Cut off the line based on which character surpasses the terminal width - ``"word"``: Cut off the line based on which character surpasses the terminal width - ``"middle"``: Trim the middle of the line until it fits the terminal width Below are examples of each mode: .. code-block:: python3 :caption: When ``mode`` is set to ``"char"`` "The quick brown fox jumped ove…" .. code-block:: python3 :caption: When ``mode`` is set to ``"word"`` "The quick brown fox jumped…" .. code-block:: python3 :caption: When ``mode`` is set to ``"middle"`` "The quick brown…the lazy dog" .. note:: ``LabeledData.Path`` behaves differently when ``mode`` is set to ``"word"``. Parts of the path will be cut and replaced with an ellipsis if the path exceeds the limit: - ``"/home/user/path/to/a/file.txt"`` becomes ``"/home/user/path/…/file.text"`` allow_ansi `````````` This parameter is present due to the way ``cutoff`` works. ``termcolor`` formatted strings contain ANSI codes (e.g. ``\x1b[31m`` for red). Normally, this wouldn't be an issue, however, when ``cutoff`` is enabled, there is the issue of the ANSI codes being cut off, which could mess up the display of the framed text. Because of this, **any strings containing ANSI codes will have their codes removed!** The only exceptions are for the objects provided by ``framed_text`` (e.g. ``Status`` and ``LabeledData``). However, if you want to allow ANSI codes to be displayed, you can set ``allow_ansi`` to true. frame_size `````````` .. versionadded:: 2026.06.03.18.00 This parameter controls how the frame is rendered. It has the following options: - ``"full"``: The default mode. Frame size is based on terminal width .. code-block:: python3 :linenos: ft: FramedText = FramedText( title="Frame Size", frame_color="blue", text=[ "A plain string", LabeledData.String( label="LabeledData.String", value="A String value", suffix="with a suffix" ), Status.Info(msg="An info message"), ] ) print(ft) .. image:: _static/imgs/quickstart_20.png - ``"dynamic"``: Frame size is based on text length .. code-block:: python3 :linenos: ft: FramedText = FramedText( title="Frame Size", frame_color="blue", frame_size="dynamic", text=[ "A plain string", LabeledData.String( label="LabeledData.String", value="A String value", suffix="with a suffix" ), Status.Info(msg="An info message"), ] ) print(ft) .. image:: _static/imgs/quickstart_21.png When using ``center_text`` in conjunction with ``"dynamic"``, the entire frame will be centered. .. code-block:: python3 :linenos: ft: FramedText = FramedText( title="Frame Size", frame_color="blue", center_text=True, frame_size="dynamic", text=[ "A plain string", LabeledData.String( label="LabeledData.String", value="A String value", suffix="with a suffix" ), Status.Info(msg="An info message"), ] ) print(ft) .. image:: _static/imgs/quickstart_22.png Data with Labels ---------------- To add data to the text with a label, it's recommended to use ``LabeledData``. ``LabeledData`` is a collection of typed objects that can be used to display data in a frame. Each class of ``LabeledData`` has the following base parameters: - ``label``: A label to assign to the text - ``value``: The value to display - ``quotes``: Whether to add quotes around the value .. versionadded:: 2026.05.15.14.30 Added ``LabeledData.Date`` .. versionadded:: 2026.05.21.16.30 - Added ``LabeledData.Bytes`` - Changed default colors for ``LabeledData.Number`` and ``LabeledData.Date`` .. versionchanged:: 2026.04.03.16.00 Used to be ``color`` and ``attrs``. - ``val_color``: The color for the value [1]_. - ``val_attrs``: The attribute(s) for the value [2]_. .. versionadded:: 2026.04.03.16.00 - ``label_color``: The color for the label [1]_. - ``label_attrs``: The attribute(s) for the label [2]_. - ``colon_match``: If true, ``label_color`` and ``label_attrs`` will be applied to the colon. .. versionadded:: 2026.05.03.14.45 - ``no_colon``: If true, the colon will be omitted from the text. Overrides ``colon_match`` .. code-block:: python3 :caption: All ``LabeledData`` classes using ``colon_match`` :linenos: ft: FramedText = FramedText( text=[ LabeledData.String( label="LabeledData.String", value="A String value", no_colon=True ), LabeledData.Number( label="LabeledData.Number", value=3.14159, no_colon=True ), LabeledData.Boolean( label="LabeledData.Boolean", value=True, no_colon=True ), LabeledData.Path( label="LabeledData.Path", value=Path("/path/to/a/file.txt"), no_colon=True ), LabeledData.Date( label="LabeledData.Date", no_colon=True ), LabeledData.Bytes( label="LabeledData.Bytes", value=65535, no_colon=True ), ] ) print(ft) .. image:: _static/imgs/quickstart_14.png ------------------------------------------------------------------------------------------------------------------------ Added suffix support to each type of ``LabeledData``. Suffixes will appear after the value. The following parameters apply to the suffix: - ``suffix``: Optional text to appear after the value - ``suffix_color``: The color for the suffix [1]_. - ``suffix_attrs``: The attribute(s) for the suffix [2]_. .. note:: The cut-off mode for suffixes is always ``"word"``. See `mode`_ for more information. .. code-block:: python3 :caption: All ``LabeledData`` classes with suffixes :linenos: ft: FramedText = FramedText( text=[ LabeledData.String( label="LabeledData.String", value="A String value", suffix="with a suffix" ), LabeledData.Number( label="LabeledData.Number", value=3.14159, suffix="with a suffix" ), LabeledData.Boolean( label="LabeledData.Boolean", value=True, suffix="with a suffix" ), LabeledData.Path( label="LabeledData.Path", value=Path("/path/to/a/file.txt"), suffix="with a suffix" ), LabeledData.Date( label="LabeledData.Date", suffix="with a suffix" ), LabeledData.Bytes( label="LabeledData.Bytes", value=65535, suffix="with a suffix" ), ] ) print(ft) .. image:: _static/imgs/quickstart_15.png Below lists the classes with additional parameters or those that differ from the base parameters: ``LabeledData.Number`` - ``round_to``: Number of decimal places to round to - ``leading_zeros``: Number of leading zeros to add - ``int_no_round``: Whether to display the value as an integer without rounding ``LabeledData.Boolean`` This class splits ``text`` and ``color`` across seperate parameters for True and False values. - ``t_text``: Text to display when the value is True - ``f_text``: Text to display when the value is False - ``t_color``: Color to use when the value is True - ``f_color``: Color to use when the value is False ``LabeledData.Date`` - ``strftime``: Date formatter for when ``value`` is a ``datetime`` object or ``value`` is not passed ``LabeledData.Bytes`` - ``show_unit``: Whether to show the unit (e.g. "KiB") and convert the bytes. If False, will show the raw bytes. - ``unit_type``: ``"iec"`` uses the IEC format (e.g. "KiB" -> Kibibytes), ``"si"`` uses the SI format (e.g. "KB" -> Kilobytes) - ``unit_match``: If True, the unit will match the styling of the value - ``unit_color``: The color of the unit [1]_ [4]_ - ``unit_attrs``: The attribute(s) of the unit [2]_ [4]_ The following ``LabeledData`` types are supported: +-------------------------+----------------------------------+ | Class | Supported Types | +=========================+==================================+ | ``LabeledData.String`` | ``str`` | +-------------------------+----------------------------------+ | ``LabeledData.Number`` | ``int``, ``float`` | +-------------------------+----------------------------------+ | ``LabeledData.Boolean`` | ``bool`` | +-------------------------+----------------------------------+ | ``LabeledData.Path`` | ``pathlib.Path`` | +-------------------------+----------------------------------+ | ``LabeledData.Date`` | ``datetime.datetime``, ``str`` | +-------------------------+----------------------------------+ | ``LabeledData.Bytes`` | ``int`` | +-------------------------+----------------------------------+ Here is an example of using ``LabeledData`` to display a string value: .. code-block:: python3 :caption: Using the ``LabeledData`` class with ``FramedText`` :linenos: ft: FramedText = FramedText( text=[ LabeledData.String( label="LabeledData.String", value="A String value", ) ] ) print(ft) .. image:: _static/imgs/quickstart_3.png .. figure:: _static/imgs/quickstart_4.png Ouptut of all of the ``LabeledData`` types printed together Displaying Statuses ------------------- ``framed_text`` also features ``Status`` objects to display messages with a status icon. ``Status`` takes the following parameters: - ``icon``: The icon to display - ``icon_color``: The color of the icon - ``sep``: The seperator between the icon and message - ``msg``: The message to display - ``text_color``: The color of the message .. versionadded:: 2026.05.09.14.45 - ``overwrite``: If true, will overwrite the previous line with the new status The Status is constructed as: ```` .. versionchanged:: 2026.04.04.14.00 - If the ``icon`` is an empty string, the seperator will not be displayed. - The Status will be constructed as: ```` - ``text_color`` will still be applied to ``msg`` ------------------------------------------------------------------------------------------------------------------------ The default ``Status`` format is: ``: `` Below is a full list of each ``Status`` and their default output: .. versionadded:: 2026.04.29.16.30 Added ``Status.Hidden`` .. code-block:: python3 :caption: Each status is printed on a new line. Note that some messages are colored. :linenos: ft: FramedText = FramedText( title="Status", frame_color="red", text=[ Status.Info(msg="This is an info message"), Status.Action(msg="This is an action message"), Status.Success(msg="This is a success message"), Status.Warn(msg="This is a warning message"), Status.Fail(msg="This is a fail message") # You can omit the 'msg=' parameter and achieve the same result Status.Hidden("This is a hidden message. It just makes the text darker.") ] ) print(ft) .. image:: _static/imgs/quickstart_9.png Displaying a Header and Divider ------------------------------- ``FramedHeader`` is like ``FramedText``, but it only displays a single line of the 'frame': .. code-block:: python3 :caption: A basic ``FramedHeader``. Without arguments, this is effectively a divider. :linenos: fh: FramedHeader = FramedHeader() .. image:: _static/imgs/quickstart_10.png Like ``FramedText``, we can color the header: .. code-block:: python3 :caption: Coloring the 'divider' red :linenos: fh: FramedHeader = FramedHeader( frame_color="red" ) .. image:: _static/imgs/quickstart_11.png Currently, this 'header' is more of a divider. To actually make it a header and add a title, we can add: .. code-block:: python3 :caption: Adding a title makes it a header :linenos: fh: FramedHeader = FramedHeader( title="Header", frame_color="red" ) .. image:: _static/imgs/quickstart_12.png ``FrameHeader`` also supports the same title formatting as ``FramedText``: .. code-block:: python3 :caption: Same example as ``FramedText``, but adapted for ``FramedHeader`` :linenos: fh: FramedHeader = FramedHeader( title="Header", frame_color="red", title_color="green", attrs=["bold", "underline"] ) .. image:: _static/imgs/quickstart_13.png Shortening Text --------------- .. versionadded:: 2026.05.04.17.15 Added ``ShortenText`` ``ShortenText`` allows for shortening a string to a specified length. The main parameters are: - ``text``: The string to shorten - ``limit``: The maximum length of the string - ``mode``: The mode to use for shortening By default, if no ``limit`` is provided, the string will be shortened to the width of the terminal using ``os.get_terminal_size().columns``. The ``mode`` behaves the same as ``FramedText``'s ``mode`` parameter. See `mode`_ for more information. The ``text`` parameter currently supports the following types: - ``str`` objects - Any ``LabeledData`` object [3]_ - Any ``Status`` object [3]_ ``ShortenText`` can be used on its own or in other classes, such as ``FramedText``. .. code-block:: python3 :caption: ``ShortenText`` used on its own :linenos: text: str = "This is a very long message that should be cut off at some point. Ideally, this should be cut off earlier than later." short_text = ShortenText(text=text) # Or for a direct str type: # short_text: str = ShortenText(text=text).__str__() # short_text: str = ShortenText(text=text).text_shorten print(short_text) .. code-block:: python3 :caption: ``ShortenText`` used with ``FramedText``. Notice the use of ``mode="word"`` :linenos: line: str = "This is a very long message that should be cut off at some point. Ideally, this should be cut off earlier than later." text: list = [ ShortenText(text=line) ] ft: FramedText = FramedText( title="Shorten Text", text=text, frame_color="red", mode="word" ) print(ft) .. image:: _static/imgs/quickstart_16.png ``str`` objects in the ``text`` list parameter of ``FramedText`` will use ``ShortenText`` to shorten strings, so no need to use ``ShortenText`` directly on them! .. code-block:: python3 :linenos: text: list = [ "This is a very long message that should be cut off at some point. Ideally, this should be cut off earlier than later." ] ft: FramedText = FramedText( title="Shorten Text built-in to FramedText", text=text, frame_color="blue", mode="middle" ) print(ft) .. image:: _static/imgs/quickstart_17.png Creating a Progress Bar ----------------------- .. versionadded:: 2026.05.09.14.45 Added ``ProgressBar`` Progress bars can be created using the ``ProgressBar`` class. This will create a progress bar that snaps to the bottom of the terminal. It will look something like this: .. figure:: _static/imgs/quickstart_18.png A basic progress bar with ``value=3`` and ``total=10`` ``ProgressBar`` takes a few parameters, however not all of them are required. **Required Parameters** - ``value``: The current value - ``total``: The total value **Data Parameters** - ``show_percent``: If true, will display the percentage of the progress bar (value / total) - ``show_values``: If true, will display the current value and total value formatted as ``"/"`` **Customization Parameters** - ``label``: A text label for the progress bar - ``show_frame``: If true, will display a frame around the progress bar, just like ``FramedText`` - ``progress_icon``: The icon to use for the progress bar - ``empty_icon``: The icon to use for the empty space in the progress bar - ``brackets``: The brackets to use for the progress bar. The input is formatted as ``(, )`` **Color Parameters** [1]_ - ``value_color``: Color of the label - ``label_color``: Color of the label - ``percent_color``: Color of the percentage - ``progress_color``: Color of the progress display - ``brackets_color``: Color of the brackets - ``frame_color``: Color of the frame **Other Parameters** - ``safe_mode``: If true, will clear the terminal and move cursor to top to ensure room for progress bar and any other data. - ``skip_init``: If true, will only initialize when ``display`` or ``update_progress`` is called The Basics of Creating a Progress Bar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The basic setup for a working progress bar looks something like this: .. code-block:: python3 :linenos: from time import sleep try: val = 0 total = 100 pb: ProgressBar = ProgressBar( value=val, total=total, ) # Loop can iterate over anything for i in range(total): # This is where code for doing stuff goes # ... # Update the progress pb.update_progress(value=i+1) sleep(0.1) pb.reset() except (EOFError, KeyboardInterrupt): ProgressBar.force_reset(show_frame=False, label=False) This is a lot, so let's break it down: - First, we define our ``ProgressBar``. Here, we are just passing values to the ``value`` and ``total`` parameters. - Next, we loop over the total value and update the value of the progress bar with ``i+1``. This will increment the progress bar by 1. - After the loop, we call ``reset`` to reset the terminal back to the state before the progress bar was displayed. We have to do this otherwise we won't be able to reach the bottom lines of our terminal. Now, the try-except block is in case there is an error in the program while the progress bar is running. Without it, we would have the same issue as if we omitted the ``pb.reset()`` call. The ``(EOFError, KeyboardInterrupt)`` used are for demonstration, but you can use any exception you want. .. warning:: The parameters for ``ProgressBar.force_reset`` **MUST** match the parameters for ``ProgressBar``. Otherwise, unexpected results may occur. The 2 parameters needed are: - ``show_frame``: Same as ``ProgressBar`` - ``label``: Set this to ``True`` if a label was used for the ``ProgressBar``. Otherwise, leave it ``False`` A more advanced example looks something like this: .. code-block:: python3 :caption: Notice the params in ``ProgressBar.force_reset`` matches the params in ``pb`` :linenos: from time import sleep try: val = 0 total = 50 print(Status.Action("Batch processing information...")) pb: ProgressBar = ProgressBar( value=val, total=total, label="Test Progress Bar", show_percent=True, show_frame=True, frame_color="blue", progress_icon='|', empty_icon=' ', ) for i in range(total): print(Status.Hidden(icon='>>', msg=f"Processing file-{i+1}.txt...")) pb.update_progress(value=i+1) sleep(0.1) print(Status.Hidden(icon='>>', msg=f"Processed file-{i+1}.txt", overwrite=True)) pb.reset() print(Status.Success("Batch processing complete!")) except (EOFError, KeyboardInterrupt): ProgressBar.force_reset(show_frame=True, label=True) Here, we are printing a status message each iteration. These print statements will not overwrite the progress bar as when ``ProgressBar`` is initialized, it will change the scrollable region of the terminal to exclude the progress bar. We also customized the appearance of the progress bar, so it now looks something like this: .. image:: _static/imgs/quickstart_19.png A full run of the above example looks like this: .. image:: _static/imgs/quickstart_g2.webp Important Notes ~~~~~~~~~~~~~~~ ``ProgressBar`` is designed to be used on its own, not in any other class within ``framed_text``. Additionally, it is important to call ``reset`` on the progress bar when you are done with it. Not doing so may lead to unexpected behavior. Currently, the progress bar does not handle resizing of the terminal window. Avoid resizing the window while the progress bar is running. Creating a Spinner ------------------ .. versionadded:: 2026.05.12.17.00 Added ``Spinner`` class Spinners are similar to progress bars, but don't show any information by themselves. However, the ``Spinner`` class can accept text to display next to the spinner. ``Spinner`` takes the following parameters: - ``text``: Text to display next to the spinner. Omit for no text. - ``icons_id``: ID string of one of the built-in icon sets. - ``done_icon``: Icon to use for when the spinner is complete. - ``custom_icons``: A list of strings to use as the spinner icon. Overrides ``icons_id`` - ``interval``: The delay between spinner icon updates. - ``position``: Where the spinner should be placed on a line. - ``indent``: How many spaces the line should be indented. - ``spinner_color``: Color of the spinner icon while active. [1]_ - ``done_color``: Color for the spinner icon when stopped. [1]_ ``Spinner.BUILTIN_ICONS`` contains all the spinner animations built into the library. It's formatted as ``: ``, with the ``id`` being used for the ``icons_id`` parameter. Each string in the list is one frame of the spinner animation. The main functions of ``Spinner`` include: - ``start()``: The main method of starting the spinner. It optionally takes a ``text`` parameter. - ``stop()``: Will preform the following actions: 1. Stops the current spinner 2. Removes or replaces the spinner on the line a. If a ``done_icon`` was provided OR one was set earlier, it will replace the spinner. b. If none was provided OR ``done_icon`` wasn't set earlier, the spinner will be removed. .. warning:: ``Spinner.start()`` will hide the cursor until ``Spinner.stop()`` is called. To prevent cases where the cursor remains invisible after force exiting the program, include ``Spinner.stop()`` in your try-except block as shown in the examples below. - ``update()``: Allows changing values of the spinner. .. note:: The following are the only values that can be changed **while the spinner is running**: - ``done_icon`` - ``done_color`` - ``text`` Examples ~~~~~~~~ A very simple spinner looks something like this: .. code-block:: python3 :linenos: from time import sleep sp: Spinner = Spinner() try: sp.start() sleep(10) # Some task here sp.stop() except (EOFError, KeyboardInterrupt): sp.stop() .. image:: _static/imgs/quickstart_g3.webp Colors ------ Most classes in ``framed_text`` have parameters for ``termcolor`` colors. The value can be either a ``termcolor`` color code or an (R, G, B) tuple, where each value is between 0 and 255. For a full list of ``termcolor`` color codes, see `termcolor's Text Properties `_. Attributes ---------- .. attention:: Not all of termcolor's attributes are supported by every terminal emulator or operating system. **Your milage may vary** Most classes in ``framed_text`` have parameters for ``termcolor`` attributes. All ``termcolor`` attributes are supported. Below is a list of all valid attributes currently available: - ``bold`` - ``dark`` - ``italic`` - ``underline`` - ``blink`` - ``reverse`` - ``concealed`` - ``strike`` .. figure:: _static/imgs/quickstart_g1.webp Showcase of all attributes using ``FramedText`` and ``LabeledData.String`` ------------------------------------------------------------------------------------------------------------------------ Notes ----- .. [1] See `Colors`_ for more information. .. [2] See `Attributes`_ for more information. .. [3] Uses a custom method of shortening text, typically found in their source class. These will not use ``ShortenText``. See their respective sections for more information. .. [4] Overrides ``unit_match`` value