A simple yet powerful TUI framework for your Python (3.7+) applications

Overview

title

A simple yet powerful TUI framework for your Python (3.7+) applications

pip3 install pytermgui

PyPI version Pylint quality

Core principles

PTG was written with some core ideas in mind, such as:

  • Pythonic syntax
  • Flexible systems
  • High quality code
  • Extensibility by design

What we provide

An example to get started with

# Note: This example uses the auto-conversion syntax. 
#       For more info, check out `help(pytermgui.auto)`.

import sys
from pytermgui import WindowManager, Window

manager = WindowManager()
window = (
    Window(min_width=50)
    + "[210 bold]My first Window!"
    + ""
    + "[157]Try resizing the window by dragging the right border"
    + "[157]Or drag the top border to move the window"
    + "[193 bold]Alt-Tab[/bold 157] cycles windows"
    + "[193 bold]CTRL_C[/bold 157] exits the program"
    + ""
    + ["New window", lambda *_: manager.add(window.copy().center())]
    + ["Close current", lambda _, button: manager.close(button.parent)]
    + ["Exit program", lambda *_: sys.exit(0)]
)

manager.add(window)
manager.run()

readme wm gif

Some screenshots

hello_world bezo calc

Documentation

As the project is in its infancy, dedicated documentation is not yet available.

If you are interested in help about anything the module provides, you can read its docstring:

)" ">
python3 -c "help(pytermgui.)"

However, proper documentation is coming once the API is stable.

Comments
  • [BUG] pip install hangs on windows.

    [BUG] pip install hangs on windows.

    Describe the bug As the title says, when Installing on windows with python3.exe -m pip -vv install pytermgui the installation hangs.

    To Reproduce

    1. run python3.exe -m pip -vv install pytermgui
    2. wait

    Expected behavior pytermgui to be installed.

    Screenshots

    Collecting pytermgui
      Created temporary directory: C:\Users\MyUser\AppData\Local\Temp\pip-unpack-ijudf3ut
      Looking up "https://files.pythonhosted.org/packages/c9/ce/2e249bae470c52429b1c93b5013db52f6c7105a82054ce7e88df08494bd8/pytermgui-2.0.0.tar.gz" in the cache
      Current age based on date: 2986
      Ignoring unknown cache-control directive: immutable
      Freshness lifetime from max-age: 365000000
      The response is "fresh", returning cached response
      365000000 > 2986
      Using cached pytermgui-2.0.0.tar.gz (62 kB)
      Added pytermgui from https://files.pythonhosted.org/packages/c9/ce/2e249bae470c52429b1c93b5013db52f6c7105a82054ce7e88df08494bd8/pytermgui-2.0.0.tar.gz#sha256=6cdd4636278bf8ef008508a9327576726f2caaaf19f694a855e3b475b1681dc3 to build tracker 'C:\\Users\\MyUser\\AppData\\Local\\Temp\\pip-req-tracker-eznv_81d'
      Running setup.py (path:C:\Users\MyUser\AppData\Local\Temp\pip-install-a8zu6svx\pytermgui_981a92d1aa834d8086c13fa048af84be\setup.py) egg_info for package pytermgui
      Created temporary directory: C:\Users\MyUser\AppData\Local\Temp\pip-pip-egg-info-4hm9lmls
      Running command python setup.py egg_info
    

    System information

    • Windows 10 Home (21H2)
    • Python 3.10.2
    • The below traceback shows pycharm 2021.3.1, but the error still occurs in the root python3 install location.

    Possible cause After force closing the installation (Ctrl + C) the traceback indicates the installation is waiting for userinteraction str = proc.stdout.readline()

    Exception information:
    Traceback (most recent call last):
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\cli\base_command.py", line 164, in exc_logging_wrapper
        status = run_func(*args)
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\cli\req_command.py", line 205, in wrapper
        return func(self, options, args)
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\commands\install.py", line 338, in run
        requirement_set = resolver.resolve(
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\resolution\resolvelib\resolver.py", line 92, in resolve
        result = self._result = resolver.resolve(
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_vendor\resolvelib\resolvers.py", line 482, in resolve
        state = resolution.resolve(requirements, max_rounds=max_rounds)
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_vendor\resolvelib\resolvers.py", line 349, in resolve
        self._add_to_criteria(self.state.criteria, r, parent=None)
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_vendor\resolvelib\resolvers.py", line 173, in _add_to_criteria
        if not criterion.candidates:
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_vendor\resolvelib\structs.py", line 151, in __bool__
        return bool(self._sequence)
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\resolution\resolvelib\found_candidates.py", line 155, in __bool__
        return any(self)
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\resolution\resolvelib\found_candidates.py", line 143, in <genexpr>
        return (c for c in iterator if id(c) not in self._incompatible_ids)
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\resolution\resolvelib\found_candidates.py", line 47, in _iter_built
        candidate = func()
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\resolution\resolvelib\factory.py", line 201, in _make_candidate_from_link
        self._link_candidate_cache[link] = LinkCandidate(
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\resolution\resolvelib\candidates.py", line 281, in __init__
        super().__init__(
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\resolution\resolvelib\candidates.py", line 156, in __init__
        self.dist = self._prepare()
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\resolution\resolvelib\candidates.py", line 225, in _prepare
        dist = self._prepare_distribution()
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\resolution\resolvelib\candidates.py", line 292, in _prepare_distribution
        return preparer.prepare_linked_requirement(self._ireq, parallel_builds=True)
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\operations\prepare.py", line 482, in prepare_linked_requirement
        return self._prepare_linked_requirement(req, parallel_builds)
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\operations\prepare.py", line 546, in _prepare_linked_requirement
        dist = _get_prepared_distribution(
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\operations\prepare.py", line 58, in _get_prepared_distribution
        abstract_dist.prepare_distribution_metadata(finder, build_isolation)
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\distributions\sdist.py", line 49, in prepare_distribution_metadata
        self.req.prepare_metadata()
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\req\req_install.py", line 561, in prepare_metadata
        self.metadata_directory = generate_metadata_legacy(
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\operations\build\metadata_legacy.py", line 59, in generate_metadata
        call_subprocess(
      File "c:\users\MyUser\pycharmprojects\tui_project\venv\lib\site-packages\pip\_internal\utils\subprocess.py", line 204, in call_subprocess
        line: str = proc.stdout.readline()
      File "S:\Programs\Python310\lib\encodings\cp1252.py", line 22, in decode
        def decode(self, input, final=False):
    KeyboardInterrupt
    Removed pytermgui from https://files.pythonhosted.org/packages/c9/ce/2e249bae470c52429b1c93b5013db52f6c7105a82054ce7e88df08494bd8/pytermgui-2.0.0.tar.gz#sha256=6cdd4636278bf8ef008508a9327576726f2caaaf19f694a855e3b475b1681dc3 from build tracker 'C:\\Users\\MyUser\\AppData\\Local\\Temp\\pip-req-tracker-eznv_81d'
    Removed build tracker: 'C:\\Users\\MyUser\\AppData\\Local\\Temp\\pip-req-tracker-eznv_81d''```
    Bug Needs help 
    opened by Klupamos 24
  • [QUESTION] Truncate on width

    [QUESTION] Truncate on width

    I have a list of lists of strings which contains data and I want them to be visible on a scrollable container as buttons. The only problem is that they have long data which wraps to the next line. Is there a way to truncate this view to the layout/slot width so that each button can be on one line?

    opened by jonnieey 13
  • input_field.py: IndexError: list index out of range

    input_field.py: IndexError: list index out of range

    Let's use example from the README.md

    import pytermgui as ptg
    
    with ptg.WindowManager() as manager:
        demo = ptg.Window(
            ptg.Label("[210 bold]Hello world!"),
            ptg.Label(),
            ptg.InputField(prompt="Who are you?"),
            ptg.Label(),
            ptg.Button("Submit!")
        )
    
        manager.add(demo)
        manager.run()
    

    After running this script with python 3.10.5 and pytermgui 6.4.0 I see this image:

    image

    which is far off image

    After seeing this image, one can write a lot of A into the input box.

    image

    Then clicking invisible [ Submit! ] button will trigger IndexError:

      File "/home/senyai/projects/pyminimg/cyclops_go.py", line 341, in <module>
        manager.run()
      File "/home/senyai/.local/lib/python3.10/site-packages/pytermgui/window_manager/manager.py", line 197, in run
        self._run_input_loop()
      File "/home/senyai/.local/lib/python3.10/site-packages/pytermgui/window_manager/manager.py", line 143, in _run_input_loop
        self.process_mouse(key)
      File "/home/senyai/.local/lib/python3.10/site-packages/pytermgui/window_manager/manager.py", line 515, in process_mouse
        window.handle_mouse(event)
      File "/home/senyai/.local/lib/python3.10/site-packages/pytermgui/widgets/containers.py", line 796, in handle_mouse
        handled = widget.handle_mouse(event)
      File "/home/senyai/.local/lib/python3.10/site-packages/pytermgui/widgets/input_field.py", line 317, in handle_mouse
        line = self._lines[y_offset]
    IndexError: list index out of range
    

    I tried gnome-terminal and alacritty which gave me same error and visuals. Hope it help.

    Bug 
    opened by senyai 11
  • [BUG] Ctrl-C doesn't stop threads

    [BUG] Ctrl-C doesn't stop threads

    Describe the bug When running any graphics loop, using the compositor, and you execute a keyboard interrupt the thread that draws the window keeps going. Mainly found on windows 10.

    I tested this on Windows 11 and the issue doesn't exist.

    To Reproduce

    1. Use a Windows 10 machine
    2. Use Windows Terminal or Alacritty
    3. Run any of the examples
    4. Press CTRL-C
    5. Program exits, but thread keeps drawing screen which traps the terminal in the window

    Expected behavior Program exits cleanly back to terminal prompt

    Screenshots LockedInDrawWindow The above gif shows a flash of text from the interrupt then another draw call.

    LockedInTerminalInterrupt The above image shows the successful interrupt but the terminal is trapped because of a thread still being active.

    System information

    • Windows 10
    • Alacritty
    • Windows Terminal
    PyTermGUI version 6.4.0
    
    System details:
        Python version: 3.10.5
        $TERM:          None
        $COLORTERM:     None
        Color support:  ColorSystem.STANDARD
        OS Platform:    Windows-10-10.0.19043-SP0
    

    Possible cause On Windows 10 a keyboard interrupt does not stop child threads and only stops the main thread.

    Possible solution Set thread to be a daemon. When a thread is set to be a daemon it will terminate when all non-daemon threads terminate. This means when the main thread terminates so will the child thread.

    Add daemon=True to where the compositor draw thread is created

    165        Thread(name="CompositorDrawLoop", target=self._draw_loop, daemon=True).start()
    

    I have tested this on the machine that had this bug and it fixed the problem.

    NOTE: I would like to add that making the different threads daemons may solve some other issues as well.

    Bug 
    opened by Tired-Fox 10
  • [BUG] terminal.print() only honors the x position for the first line

    [BUG] terminal.print() only honors the x position for the first line

    Simple code I used:

    #!/usr/bin/env python3
    
    import os, sys
    import pytermgui as ptg
    
    with open(sys.argv[1]) as f:
        contents = f.read()
    
    ptg.terminal.clear_stream()
    ptg.terminal.print(contents, pos=(10, 0))
    
    

    Output looks like this:

              #include <stdio.h>
    
    int main() {
        printf("Hello world!");
        return 0;
    }
    

    I don't believe this is intended? There also seems to be issues with moving the cursor past the first column, but that's a separate issue.

    Bug 
    opened by leftbones 10
  • [BUG] `getch` in `_get_pixel_size` hangs when terminal doesn't have the feature implemented

    [BUG] `getch` in `_get_pixel_size` hangs when terminal doesn't have the feature implemented

    Describe the bug Calling import pytermgui spawns a Terminal; on Windows terminals (tested: Windows Terminal, Powershell, and the built-in VS Code terminal), the Terminal constructor attempts to call _get_pixel_size after sending the (ignored) ANSI terminal command [14t, to which Windows terminals do not respond. The resulting getch call blocks until a key is pressed.

    To Reproduce Steps to reproduce the behavior:

    1. On Windows, start any Python file containing import pytermgui, within Powershell or Windows Terminal.
    2. Further Python code does not run until you push any key, which causes the getch call to return (and set pixel size = (0,0) due to it not finding a ;).

    Expected behavior On terminals that don't support ANSI terminal commands, don't hang trying to get pixel size.

    Screenshots If applicable, add screenshots to help explain your problem.

    System information

    PyTermGUI v3.2.1
    
    Python: 3.9.4
    Platform: Windows-10-10.0.19041-SP0
    

    Possible solution Is it sufficient to add an additional check to get_chars (line 135 in input.py) that checks msvcrt.kbhit() prior to any getch call, and returns an empty buffer if kbhit returns false?

    Bug 
    opened by meson800 9
  • [BUG] io.UnsupportedOperation error on launch

    [BUG] io.UnsupportedOperation error on launch

    Launching PTG on Windows produces an "io.UnsupportedOperation" error.

    PTG Version: 4.3.1

    Python version: 3.10

    Code: Window using children as arguments example from README

    Screenshot:

    image

    Bug 
    opened by x10102 8
  • [BUG] inline_styles has no effect when exporting to SVG?

    [BUG] inline_styles has no effect when exporting to SVG?

    Describe the bug I'm adding an example using PyTermGUI to my Markdown Exec's gallery. Here's my code:

    from io import StringIO
    import pytermgui as ptg
    
    code = """
    while True:
        if condition:
            print("Hello")
        else:
            print("Goodbye")
    
        input()
    """
    
    with ptg.Terminal(stream=StringIO(), size=(20, 20)).record() as recorder:
        recorder.write(ptg.tim.parse(ptg.highlight_python(code)))
        print(recorder.export_svg(inline_styles=True))
    

    Whatever the value of inline_styles, I get a style tag in the final HTML. This is problematic because it affects other parts of the page.

    pytermgui

    Expected behavior No global style set in the page.

    System information

    PyTermGUI version 6.2.1
    
    System details:
        Python version: 3.8.13
        $TERM:          xterm-256color
        $COLORTERM:     truecolor
        Color support:  ColorSystem.TRUE
        OS Platform:    Linux-5.17.9-arch1-1-x86_64-with-glibc2.35
    

    Possible cause I might misunderstand the purpose of the mentioned style tag or the inline_styles option.

    Possible solution Use more specific CSS selectors to affect only PyTermGUI's own SVG.

    Bug 
    opened by pawamoy 6
  • [BUG] pip install failed - TypeError: RegexHighlighter() takes no arguments

    [BUG] pip install failed - TypeError: RegexHighlighter() takes no arguments

    Describe the bug A clear and concise description of what the bug is.

    When I attempt to install pytermgui using pip the installation fails and throws an error

    Defaulting to user installation because normal site-packages is not writeable
    Collecting pytermgui
      Using cached pytermgui-6.1.0.tar.gz (136 kB)
      Installing build dependencies ... done
      Getting requirements to build wheel ... error
      error: subprocess-exited-with-error
    
      × Getting requirements to build wheel did not run successfully.
      │ exit code: 1
      ╰─> [28 lines of output]
          Traceback (most recent call last):
            File "/home/[user]/.local/lib/python3.9/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 363, in <module>
              main()
            File "/home/[user]/.local/lib/python3.9/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 345, in main
              json_out['return_val'] = hook(**hook_input['kwargs'])
            File "/home/[user]/.local/lib/python3.9/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 130, in get_requires_for_build_wheel
              return hook(config_settings)
            File "/tmp/pip-build-env-3ngpzg9c/overlay/lib/python3.9/site-packages/setuptools/build_meta.py", line 177, in get_requires_for_build_wheel
              return self._get_build_requires(
            File "/tmp/pip-build-env-3ngpzg9c/overlay/lib/python3.9/site-packages/setuptools/build_meta.py", line 159, in _get_build_requires
              self.run_setup()
            File "/tmp/pip-build-env-3ngpzg9c/overlay/lib/python3.9/site-packages/setuptools/build_meta.py", line 281, in run_setup
              super(_BuildMetaLegacyBackend,
            File "/tmp/pip-build-env-3ngpzg9c/overlay/lib/python3.9/site-packages/setuptools/build_meta.py", line 174, in run_setup
              exec(compile(code, __file__, 'exec'), locals())
            File "setup.py", line 3, in <module>
              import pytermgui
            File "/tmp/pip-install-4s0u2_kx/pytermgui_e7e9e5f247fd4974833e1cb8344f0c75/pytermgui/__init__.py", line 20, in <module>
              from .parser import *
            File "/tmp/pip-install-4s0u2_kx/pytermgui_e7e9e5f247fd4974833e1cb8344f0c75/pytermgui/parser.py", line 121, in <module>
              from .colors import str_to_color, Color, StandardColor
            File "/tmp/pip-install-4s0u2_kx/pytermgui_e7e9e5f247fd4974833e1cb8344f0c75/pytermgui/colors.py", line 22, in <module>
              from .fancy_repr import FancyYield
            File "/tmp/pip-install-4s0u2_kx/pytermgui_e7e9e5f247fd4974833e1cb8344f0c75/pytermgui/fancy_repr.py", line 7, in <module>
              from .highlighters import highlight_python
            File "/tmp/pip-install-4s0u2_kx/pytermgui_e7e9e5f247fd4974833e1cb8344f0c75/pytermgui/highlighters.py", line 156, in <module>
              highlight_python = RegexHighlighter(
          TypeError: RegexHighlighter() takes no arguments
          [end of output]
    
      note: This error originates from a subprocess, and is likely not a problem with pip.
    error: subprocess-exited-with-error
    
    × Getting requirements to build wheel did not run successfully.
    │ exit code: 1
    ╰─> See above for output.
    
    note: This error originates from a subprocess, and is likely not a problem with pip.
    

    To Reproduce Steps to reproduce the behavior:

    1. Open a terminal on a machine without pytermgui installed
    2. Type python3 -m pip install pytermgui and hit enter
    3. See the error

    Expected behavior A clear and concise description of what you expected to happen.

    The installation to work successfully

    Screenshots If applicable, add screenshots to help explain your problem.

    System information

    Alpine on WSL on Windows 10

    Add the output of "ptg --version" in this box.
    

    Possible cause If you have a hunch on what might be causing this, please add it here.

    Seems like something to do with the dataclass meaning that RegexHighlighter doesn't get an init ?

    Possible solution If you know a way we could fix this, please add it here.

    I don't know much about dataclasses but maybe this link is relevant

    Bug 
    opened by EdwardTheLegend 6
  • [BUG] io.UnsupportedOperation: truncate

    [BUG] io.UnsupportedOperation: truncate

    Describe the bug I was trying out one of the examples in the documentation, but it kept throwing an exception complaining about there being no method called truncate. I started to follow the traceback and found out that it was calling sys.stdout.truncate(0)... which doesn't exist (at least on windows it doesn't).

    To Reproduce Steps to reproduce the behavior:

    1. Paste and run the following into an IDE
    import pytermgui as ptg
    
    
    if __name__ == "__main__":
        with ptg.WindowManager() as manager:
            window = ptg.Window(
                "[wm-title]My first window!",
                "",
                ["Exit", lambda *_: manager.exit()],
            )
    
            manager.add(window)
            manager.run()
    
    1. See error (pasted the one I'm getting below if you don't get one)
    Exception in thread WM_DisplayLoop:
    Traceback (most recent call last):
      File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.8_3.8.2800.0_x64__qbz5n2kfra8p0\lib\threading.py", line 932, in _bootstrap_inner
        self.run()
      File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.8_3.8.2800.0_x64__qbz5n2kfra8p0\lib\threading.py", line 870, in run
        self._target(*self._args, **self._kwargs)
      File "c:\Users\Conno\pyvenv\lib\site-packages\pytermgui\window_manager.py", line 447, in _loop
        animator.step()
      File "c:\Users\Conno\pyvenv\lib\site-packages\pytermgui\animations.py", line 120, in step
        if animation.step():
      File "c:\Users\Conno\pyvenv\lib\site-packages\pytermgui\animations.py", line 69, in step
        step_callback(self.target)
      File "c:\Users\Conno\pyvenv\lib\site-packages\pytermgui\window_manager.py", line 998, in _on_step
        ret_val = step_callback(_target)
      File "c:\Users\Conno\pyvenv\lib\site-packages\pytermgui\window_manager.py", line 646, in _on_step
        self.nullify_cache(window)
      File "c:\Users\Conno\pyvenv\lib\site-packages\pytermgui\window_manager.py", line 478, in nullify_cache
        self.redraw()
      File "c:\Users\Conno\pyvenv\lib\site-packages\pytermgui\window_manager.py", line 977, in redraw
        terminal.write("\x1b[2J")
      File "c:\Users\Conno\pyvenv\lib\site-packages\pytermgui\animations.py", line 69, in step
        step_callback(self.target)
      File "c:\Users\Conno\pyvenv\lib\site-packages\pytermgui\window_manager.py", line 998, in _on_step
        ret_val = step_callback(_target)
      File "c:\Users\Conno\pyvenv\lib\site-packages\pytermgui\window_manager.py", line 646, in _on_step
        self.nullify_cache(window)
      File "c:\Users\Conno\pyvenv\lib\site-packages\pytermgui\window_manager.py", line 478, in nullify_cache
        self.redraw()
      File "c:\Users\Conno\pyvenv\lib\site-packages\pytermgui\window_manager.py", line 977, in redraw
        terminal.write("\x1b[2J")
      File "c:\Users\Conno\pyvenv\lib\site-packages\pytermgui\terminal.py", line 390, in write
        self.clear_stream()
      File "c:\Users\Conno\pyvenv\lib\site-packages\pytermgui\terminal.py", line 412, in clear_stream
        self._stream.truncate(0)
    io.UnsupportedOperation: truncate
    

    Expected behavior I was hoping for some kind of window to show up in the terminal. I don't think an exception counts as a window. :[

    Screenshots I don't think any screenshots are necessary.

    System information

    fatal: not a git repository (or any of the parent directories): .git
    PyTermGUI v4.3.1
    
    Python: 3.8.10  
    Platform: Windows-10-10.0.19043-SP0
    

    Possible cause The program is calling the truncate method in sys.stdout, which does not exist.

    Possible solution Looking at the traceback, it seems like this occurs whenever the program tries to call self.clear_stream() in the Terminal class. I could try creating another way of clearing the screen in sys.stdout.

    Bug 
    opened by SkiHatDuckie 6
  • Add `_Terminal.no_echo` context manager

    Add `_Terminal.no_echo` context manager

    modified: pytermgui/ansi_interface.py

    • Fixed docstring of _update_size function
    • Added save points of console handles
    • Added context manager for no_echo mode

    modified: tests/yamlload.py

    • Fixed typo in line 33
    opened by UltraStudioLTD 6
  • [BUG] Cursor not visible in Splitter

    [BUG] Cursor not visible in Splitter

    Describe the bug In elements placed inside Splitter (e.g. Splitter(InputField(...)), same applies to buttons and maybe other stuff) cursor is not displayed making text input extremely inconvenient

    To Reproduce Steps to reproduce the behavior:

    1. Create some elements in Splitter
    2. Navigate to them (using mouse or arrow keys)

    Expected behavior Cursor should be visible as it is in other elements e.g. in Container

    Screenshots image image

    System information

    PyTermGUI version 7.3.0
    
    System details:
        Python version: 3.10.9
        $TERM:          xterm-256color
        $COLORTERM:     truecolor
        Color support:  ColorSystem.TRUE
        OS Platform:    Linux-6.1.1-arch1-1-x86_64-with-glibc2.36
    
    Bug 
    opened by xezo360hye 0
  • [BUG] IndexError in multiline InputField

    [BUG] IndexError in multiline InputField

    Describe the bug When using multiline InputField, there are at least 2 ways to get IndexError, both of them lead to app being freezed or crashed which is annoying

    To Reproduce Steps to reproduce the behavior:

    1. Press Enter while there is no characters in the input field
    2. On a newline, try to remove last character. If the previous line is not empty, pressing backspace will raise an error, though app does not exit and just freezes

    Expected behavior It should normally edit text

    Screenshots image image

    System information

    PyTermGUI version 7.3.0
    
    System details:
        Python version: 3.10.9
        $TERM:          xterm-256color
        $COLORTERM:     truecolor
        Color support:  ColorSystem.TRUE
        OS Platform:    Linux-6.1.1-arch1-1-x86_64-with-glibc2.36
    

    Possible cause Both errors happen in input_field.py when trying to get self._lines[...] and is related to current row

    Possible solution Sanity check for index (row) and array length

    Bug 
    opened by xezo360hye 0
  • [BUG] Checkbox not visible in Splitter

    [BUG] Checkbox not visible in Splitter

    Describe the bug Checkbox not rendered correctly inside Splitter in 7.2.0. Works as expected in 7.1.0. Checkbox action does work via mouse if right co-ords clicked.

    To Reproduce Steps to reproduce the behavior:

            with ptg.WindowManager() as manager:
                window = (
                    ptg.Window(
                        "",
                        ptg.Splitter(
                            ptg.Checkbox(), # isn't visible when not selected
                            ptg.Label("some label"),
                            ptg.Checkbox(), # isn't visible when not selected AND doesn't contribute space to layout until selected
                            ptg.Label("some label"),
                        ),
                       ptg.Checkbox(), # renders fine
                        "",
                        ptg.Button("Done", lambda *_: return),
                        width=80,
                        box="DOUBLE",
                    )
                    .set_title("[210 bold]Some Title")
                    .center()
                )
    
                manager.add(window)
    
    

    Expected behavior Visible checkboxes :)

    Screenshots

    7.2.0 (nothing selected) image

    (second checkbox selected) image

    7.1.0 image

    System information

    PyTermGUI version 7.2.0
    
    System details:
        Python version: 3.8.13
        $TERM:          xterm-256color
        $COLORTERM:     truecolor
        Color support:  ColorSystem.TRUE
        OS Platform:    Linux-5.15.0-39-generic-x86_64-with-glibc2.35
    
    Bug 
    opened by edkirk30 0
  • [Announcement] New documentation, state of the project

    [Announcement] New documentation, state of the project

    Hey there!

    Updates to the library have slowed down in recent months, mostly due to university work loads increasing, and not leaving me with enough time to work on PyTermGUI.

    This should be temporary, and I expect to be back to work relatively soon. Apologies about the delays! There is some very exciting work in the pipeline, such as a Layout based container widget and a smarter compositor.

    There is a still in progress new documentation site, which you can access at a temporary address, or the new-docs branch. It is much better than what we currently have, and is not far from completion.

    I'll try my best to get back to working as soon as I can, and again, apologies for going dark on the GitHub. I talk more regularly in our Discord server, so for more updates you can come and join us!

    :rocket:

    Documentation 
    opened by bczsalba 0
  • [Example] Quit only possible in linux via mouse

    [Example] Quit only possible in linux via mouse

    I was testing the example examples/simple_app.py and noticed that "quit" is only accessible in Linux. And even there only with mouse interaction. On windows (PowerShell) even mouse interaction does not work. For a new testing user of pytermgui this is very disorientating. Since the knowledge is lacking if this is an easy fix or a lacking implementation of the library.

    That said I like what I see. Keep it up.💚

    opened by XenonR 1
Releases(v7.3.0)
  • v7.3.0(Nov 17, 2022)

    The primary focus for this release is the new documentation, but there is a lot of minor changes that slipped through in the meantime. The new documentation is great; it has much more in-depth content on most parts of the library, it looks amazing and it's a lot less of a hassle to maintain! It also has build-time screenshot generation using this very module, so all the SVGs will always remain up to date.

    Changelog

    Additions

    • Add support for SHIFT+ scroll events (74722db6787b733b75e3515dfc086cf0338235b8)
    • Add shade number indicators to Palette.print (06f2ec78d1b31d2a059035e72e8d1b014c929b81)
    • Add inline widget runner (ba19d36f51f5b16c9871070953fa348b6553504f)

    Bugfixes

    • Fix incorrect macro caching behaviour (321f1f9549d03285d44904c344bd2551b795e0e6)
    • Fix various issues and misbehaviours with SVG exports
    • Fix incorrect placement of InputField cursor (7281c5716e5662d1cfa50d11c5da50d8f3e44d28)

    Refactors

    • New MkDocs based documentation

      While the previous documentation was alright, it missed a lot of things. MkDocs makes it a bit easier to create step-by-step style documentation pages, which was exactly what we needed. We also made use of Termage to make it a lot more dynamic.

    • Change terminal.py -> term.py and serializer.py -> serialization.py to avoid naming conflicts (e38603ee390141dcdb7b0d090f8684f4e331b68f)

    • Improve pseudo token behaviour by parsing it as a new token type (f19b897ba99c8270c71e6f34c30e2a33ef4390f9)

    • Start generating semantic colors (success, warning, error) by blending with the primary (2daee90a3abe47aa632a7ca876151062946f0784)

    Removals

    • Remove is_bindable widget attribute (866cd0951d3f3471ae0e62631ba59834912fd8e1)

      This was only used as an arbitrary limitation, one that was not needed in the library.

    Showcase

    Screenshot 2022-11-17 at 15 05 44 Screenshot 2022-11-17 at 15 05 53 Screenshot 2022-11-17 at 15 06 00 Screenshot 2022-11-17 at 15 06 07

    Source code(tar.gz)
    Source code(zip)
  • v7.2.0(Aug 5, 2022)

    This version brings the long-awaited (at least by myself) color palette system!

    Before that, the new #auto TIM pseudo-tag deserves a mention. It makes the parser look at the currently applied background color, and it is replaced with a color that properly contrasts it while parsing! This way, [alias #auto]Text, will always be legible, regardless of the meaning of alias. It is also automatically used by all widget styles (whenever there is no foreground specified), so you can just define a style as @surface+1, and PTG will make sure it looks nice and readable!

    Anyways, the palette. Here is the gist of it:

    • The new module palettes provides a Palette class
    • This class can generate mashing colors from just one primary color input, with multiple possible strategies
    • The whole module now has a default palette that can be accessed using ptg.palette and in markup

    TIM gains the following sets of new aliases:

    • primary
    • secondary
    • tertiary
    • accent
    • surface
    • surface2
    • surface3
    • surface4
    • success
    • warning
    • error

    Each color has 7 shades, and each shade a foreground and background variant. The base color (i.e. with no shade modifications) use the name as written above, and every other alias is defined as {name}{+/-}{shade_amount}, like primary-3 for the darkest shade of primary, andsurface+2for the second-brightest surface shade. Each alias comes complete with a background variant bound to@{alias}`, such as @secondary+2.

    It's easier to show than tell, so here is the new default palette, as exported by ptg --palette --export-svg <filename>: palette

    Changelog

    Additions

    • Add various color manipulation utilities
    • Add #auto TIM pseudo-tag that always gives properly contrasted foreground text
    • Add palettes module for framework-wide color generation & configuration
    • Add Synchronized Output support
    • Add FancyReprWidget
    • Add ptg --palette flag

    Bugfixes

    • Fix markup aliases getting literalized during parsing.eval_alias & MarkupLanguage.alias
    • Fix background colors creating vertical seams in SVG exports
    • Fix colors getting localized pre-maturely

    Refactors

    • Make all the ptg program & all builting widgets use the global palette
    • Prefix all ANSI colors with ansi-

    Showcase

    Here is my home-grown project launcher, lens, using the new default color palette (and an upcoming new button widget, but that's for the next release notes):

    Screenshot 2022-08-05 at 23 53 46

    ...and now, using it's custom-defined palette, using the primary color #58A46F:

    Screenshot 2022-08-05 at 23 54 32

    Here is ptg in the new default color palette:

    Screenshot 2022-08-05 at 23 55 29

    ...and now with a bunch of randomly generated ones:

    Screenshot 2022-08-05 at 23 55 35 Screenshot 2022-08-05 at 23 55 42 Screenshot 2022-08-05 at 23 55 46 Screenshot 2022-08-05 at 23 55 55 Source code(tar.gz)
    Source code(zip)
  • v7.1.0(Jul 27, 2022)

    This minor release mostly aims to fix up some issues caused in previous releases, as well as tighten up InputField cursor behaviour.

    Note that the release size of the project became enormous since the move to pyproject.toml for building. This should be resolved by the next update.

    Changelog

    Additions

    • Re-introduce InputField prompt attribute (#90)

    Bugfixes

    • Fix ptg --version (#89)
    • Start wrapping InputField cursor when it goes outside of the given width (634c1b5eb13e58ece182dee0c34555939fcb5e1e)
    • Fix incorrect KeyboardButton label generation (#88)

    Showcase

    Here is a sneak-peak of the upcoming update to the file-definition system, which will add things like selector-based targeting, native markup support and more!

    Screenshot 2022-07-27 at 15 06 27

    Source code(tar.gz)
    Source code(zip)
  • v7.0.0(Jul 24, 2022)

    This release brings completely re-written TIM implementation to the library. It is significantly faster (~2x for markup without macros, >10x for markup with macros) than the previous version, and it's a lot easier to maintain and improve upon.

    The previous hyperlink syntax ([!link(https://example.org)]Example site[/!link]) is now deprecated in favour of a new, much simpler one:

    [~https://example.org]Example site[/~]
    

    There have also been a couple of changes to SVG exports to make them more accurate and aesthetically pleasing. We also support the inverse style for them as well!

    Changelog

    Changes marked in bold are API-breaking.

    Additions

    • Support CSS color names in TIM code (77d2ca98150d48143e9a52eaa2e36578c369e4d6)
    • Support terminal resize events on Windows (@Tired-Fox, #80)
    • Add ignore_any parameter to Widget.execute_binding (68866e63fcba0dd36f5a1165966cb5b2377bc43b)

    Bugfixes

    • Fix InputField handling clicks & drags started outside of it (#72, #75)
    • Fix CTRL_C not killing compositor thread by making it a daemon (#78)
    • Fix contents of widget.positioned_line_buffer being duplicated before and after vertical alignment (#70)

    Refactors

    • Rewrite of the TIM engine (now at version 3!) (#84)
    • Move TIM highlighting from an instance method to a highlighter (635b6f60467aa4b854c72238f2bc9edc710576b8)
    • Move to pyproject.toml-based builds (#82)
    • Stop relying on visibility=hidden in SVG exports (d070724a591f6c0f62016944e2d49ed1382d9805)

    Removals

    • Remove get_applied_sequences helper function (a7d41bd819abd1ea481dc536090199a98c9330e7)

    API updates

    | Type | Change | Alternative | Comment | |--------------|---------|-----------|------------| | Removal | get_applied_sequences | A custom tokenization based implementation | This function was no longer used internally, and if someone needed it the new tokenizers are a much more performant and smart way to go about implementing it. | | Removal | MarkupLanguage.prettify_markup | highlight_tim | Using regex-based highlighting allows the output markup to be completely identical char-by-char to the source, whereas the previous token based implementation had a tendency to change things around. It's also much less LOC and faster. | | Deprecation | Markup hyperlink syntax !link(https://example.org) | The new ~https://example.org syntax | Previously hyperlinks were implemented as macros, but they were very messy under the hood. A first-class syntax for them is vastly superior. | | Refactor | The role of StyledText | N/A | Previously, StyledText was meant to be barely detectable when used. It was returned in various places, but wanted to not be a thing you thought about often. Now it's on an opt-in basis, and it no longer tries to pass as a str. It's immutable, and is only meant to be generated by MarkupLanguage.group_styles or StyledText.group_styles. You can also now create them from markup, not just ANSI-coded text. |

    Showcase

    CSS colors Style modes Example parse Speed comparison Note that since the above image, tim-v3 went down to ~180-190 ns per parse

    Source code(tar.gz)
    Source code(zip)
  • v6.4.0(Jun 14, 2022)

    This release brings the ability to use on_{mouse_event} functions to handle specific events, instead of having to sort manually within handle_mouse. This is done within Widget's handle_mouse method, so it will be implemented by all widgets that call super().handle_mouse before doing their own handling. It also improves general mouse handling behaviour, and makes it all a bit more predictable.

    There is a minor change in return-value semantics as well. Previously, handle_mouse() == True stood for "I was able to handle this event, do not bubble it up". This wasn't very specific, and there were some special cases where undefined behaviour would occur. It has now been changed to "I want to handle more mouse events, even if they aren't directly targeting me". This essentially allows a widget to declare itself "sticky" for certain mouse events, and "unsticky" when it is no longer needed.

    Changelog

    Additions

    • Add hover highlighting for Button (dcf5b0d8f2981211a33aa30f12009ad0ddb371e3)

    Bugfixes

    • Fix Splitters only sending mouse events on the first row of height (ad5cffc0327bb2a9eae504a7b4fc7d0c1f2ca12e)

    Refactors

    • Improve mouse input cascade logic (ae971020fe6090eaa3c80cecd3b6d9d60f87ef64)

    • Implement semantic mouse handlers (f11f524a31375b4ccb19e7bbff96395bcf38e8f8)

      All widgets now have some "implicit" callbacks for each specific mouse event. They are only called when defined, so it is fully backwards compatible. They all follow the syntax of:

        on_{event}
      

      Where event can be any snakeified mouse action name. For example, LEFT_CLICK calls on_left_click, and SCROLL_UP calls on_scroll_up. For most events, there is a lesser layer of specificity allowed. For example, you usually want to handle both scroll directions with the same function. Because of this, we also allow defining on_scroll to deal with both events. Whenever multiple specificity level handlers are defined for the same action, the most specific will be used. For example, a widget with both on_drag and on_left_drag will invoke on_drag for RIGHT_DRAG, and on_left_drag for LEFT_DRAG.

    Showcase

    Here is a little mouse handling demo I created while writing this version. All mouse actions are defined with custom on_{event} handlers, where both drag events return True, and everything else False. This makes those events stick to the tile that started handling them.

    https://user-images.githubusercontent.com/66030897/173597243-8bc30299-c342-40ca-8393-2203841b43fe.mp4

    Source code(tar.gz)
    Source code(zip)
  • v6.3.0(Jun 5, 2022)

    The previous InputField implementation was highly restrained by the lacking (and slow) break_line implementation present at the time. Since that was recently improved a lot, the manually placed restrictions didn't make much sense anymore. There is now support for multiline text editing, syntax highlighters and more!

    Changelog

    Refactors

    • Refactor InputField (6cd72d677ba139d7a31ae59020e508ae1edadc36)

    • Start caching Token.sequence to improve performance (9638e9513796b51a64a58134b39b245397732854)

    • Start lazy-evaluating terminal resolution (4a7c25baa6097bf216833ca74712713577acb8d9)

      Some terminals don't support this feature, so we used to have a very short (0.01) second timeout for an emulator to respond. This was way too short in some situations, leaving the response to be printed to STDOUT instead of being captured. The bigger problem was that there is basically no code in the wild that actually uses this feature: it was implemented for the still-upcoming image support, but no other systems really use it. Because of this, it was pretty useless to query it on every startup.

    Bugfixes

    • Use SVG export prefix as the class of the generated text elements (7c977f15fdb43649aa02f7e924290dbfdcc61e09, #67)

      Previously, the text style selector selected every SVG in the document. This was problematic, as it messed up non-PTG SVGs displayed alongside our own.

    • Fix Inspector not resizing to custom global terminals (0bb071711586ad8ee129fd85df14ea9eae3b06bb)

    Additions

    • Add break_line fill argument (1426edc9627577764d4e286a3a65f8b6593afb46)

      This is currently unused by the library at large, but it allows padding out every yielded line to the target width using the given character. Can be pretty useful.

    • Add chrome SVG argument (182258517ff0e7d459b9c7a42a9413ffeed629fc)

    Showcase

    Here is a simple file I wrote using sandbox/input_field.py, a file created from examples/boilerplate.py in barely any code. Try it yourself!

    Screenshot 2022-06-05 at 14 09 13

    Source code(tar.gz)
    Source code(zip)
  • v6.2.2(May 26, 2022)

    Web compatibility strikes again. While Chrome supports alignment-baseline for SVG text tags, Firefox only supports dominant-baseline. Then, Safari comes in as a unicorn proclaiming (very quietly) that it supports neither.

    All hail dy, I guess!

    Changelog

    Bugfixes

    • Fix text being misaligned in both Firefox and Safari

    Refactors

    • Reduce redundancy in SVG export dimensions
    Source code(tar.gz)
    Source code(zip)
  • v6.2.1(May 25, 2022)

    This release mainly targets my new mkdocs plugin, termage, which allows you to insert SVGs of Python program output, generated at build time. Its documentation website is still waiting for DNS propagation, but it uses the plugin as well. You can expect a revamp of the documentation using mkdocs and termage very soon!

    For that system to work, WindowManager needed to gain the capability of running in headless mode, so that it can render an output and quit without interaction.

    Changelog

    Bugfixes

    • Fix \n being escaped when highlighting python (48a365a24f9b837108a1cf946bcc86af3b84cda0)

    Refactors

    • Add WindowManager.autorun class attribute (6ea6044afcb7e11603fd2c5ed00ffe0ef2a7e699)

    Showcase

    The aforementioned documentation website: 127 0 0 1_8000_ (1)

    Source code(tar.gz)
    Source code(zip)
  • v6.2.0(May 24, 2022)

    Changelog

    Bugfixes

    • Fix StandardColor HEX and RGB being indexed from the wrong pool (66384acbb838df6f4c262b03fe595df8fbeb6fd5)
    • Fix overly greedy ~~yeeting~~ optimization of ttype=POSITION tokens (2f7a5616f0909499d1f391eed4f75b77bc667a82)
    • Fix ttype=POSITION tokens acting unpredictably when multiple were present in a string (c2c227f074c762a6607b4b5be7ba6d4da969c68e)

    Additions

    • Add WindowManager.autorun attribute (ab0fd94871bd5f03246ef24db8f6d39a7f4d41b4)

    Refactors

    • Implement usage of SVG tags when exporting (589e65003daab3cb374589b6eaa1fa6176272834)

      Previously, we were using foreignObject SVG tags to render inner content. This worked, but only in browsers, and looked ever so slightly different between each of them. We now use the proper SVG tags, and thus our exports are now real images not linked to browsers!

      You can also now export screenshots from a WindowManager application, and they look the same as they did in your terminal. This is allowed by the 2 position token fixes above. As with the previous version, this uses your terminal's background & foreground colors, as well as its size when generating. Makes it actually look like it's a screenshot of your terminal!

    export

    Showcase

    All of the images here are straight-up SVGs dragged into the release note, no conversions or anything necessary.

    screenshot export

    Thank you to everyone for the 1000 stars the project recently reached. It's an incredible achievement, and I am beyond grateful for the support.

    ⭐ 🚀

    Source code(tar.gz)
    Source code(zip)
  • v6.1.0(May 17, 2022)

    This version was mostly for bugfixing, but it introduces the new __fancy_repl__ protocol into the library.

    The purpose of this protocol is for objects to gain control over how they are displayed in a pretty REPL environment. See the docs for more info.

    There is also now support for string format specs for Color objects. You can now do things like:

    markup = f"[{color:tim}]Text"
    

    and I think that's pretty neat.

    Changelog

    Additions

    • Introduce __fancy_repr__ protocol (09bcb0ef1b92a5217b12576f7a60e2a62e292c49)

      This protocol is somewhat inspired by rich's __rich__, but tries to be agnostic to the underlying ANSI interface used. It can be used to customize highlighting an object's repr output.

      It is already implemented by all the Color classes, and RegexHighlighter. More (probably) to come.

    • Add Color format specifiers (c529c2c0b805ff9fe5f357023f70e55a3ee8f985)

    • Add Animation.pause & Animation.unpause (bf7ddbdf554c3228ca0860c6adfa900721147e1c)

    Bugfixes

    • Fix scrolled widgets not getting positioned correctly (29a2aebcf1d98dae215497170e14039eccd1f290)
    • Fix an issue with 2-bit colors being interpreted as 8-bit ones (632ac1b957b3369e139dff17639d90b10efb00cd, #56)

    Refactors

    • Improve highlight_python vs strings (8a9f63a7977facbddb7855ce1f14f33fa1a82929, 9e1042fa85df3123be5a099f299321c65e565206)

    Showcase

    Screenshot 2022-05-17 at 17 09 46

    Source code(tar.gz)
    Source code(zip)
  • v6.0.0(May 12, 2022)

    This version was originally meant to focus on the new layout system, but things got out of hand quickly. In the end, we have the aforementioned feature, alongside a completely reimagined & much more useful CLI, a regex-based syntax highlighting base, major performance improvements and some general QOL things. There unfortunately are some (relatively minor) API changes, which is why this version is 6.0.0 instead of 5.1.0.

    Changelog

    • Remove Window.allow_fullscreen, Window.toggle_fullscreen (114da3a3d769d6abd72a8727ed036b1e947c0a23)

      These methods are no longer really relevant in the new layout-based system. They were also handled in a really odd way from the library's side, so it should be one less bug-prone area to figure out. You can now set windows fullscreen using the layout system:

       manager.layout.add_slot("Body")
       manager.add(window, assign="body")
      

      More on the layout API later.

    Refactors

    • Add new, customizable window blur styles (114da3a3d769d6abd72a8727ed036b1e947c0a23)

      The old style was visually impressive, however also prone to causing bugs that could not be resolved with either stripping functionality or changing the library source. The new version follows traditional and modern TUIs more closely by only changing the color of borders, and is actually customizable. However, since there are new styles for both blurred and focused states for both the corner and border set of characters, a small helper was also added, Window.set_focus_styles.

    • Rename all builtin aliases to follow the domain.item naming scheme (3a416f5f7d2dbc80328478ea16fddb4e980d1437)

    • Improve animation stability (c806b975c7815c876eb6845637c9f125c2f26c61, 05b61268479696298873cf616b4696ccab77b8fe)

    • Start caching real_length, strip_markup & strip_ansi results (a07ce9f606eaa96ee923e97a437edf375b89552d, 532e3ccc66fee81e4e9bfc0df0407ca72e4705c0)

      This was altogether a sub-10 line change, but it actually has huge performance implications. It will also be useful for the future, more advanced compositing running at an acceptable speed.

    • Refactor StyledText to only tokenize on-demand (b15eba881cb7a83b0c5302ae6855ec949db5a4b6)

    • Rewrite the pattern used to match markup to improve how escapes are handled (d656b7534d15769c375e9f083adc7896052ba4a1, 5a37470ac072746ee54c2029a01dcaf00832a7d8)

    • Introduce new, layout based CLI with an RGB colorpicker & inspector (31433362b208c5cc3f4c879004e69c913f361980)

      This started off as a way to showcase the new layouts, and wasn't even supposed to be a full rewrite. However, I eventually realized how ridiculously over-engineered the previous CLI was, so I decided to come up with a new system. There is a new app, Inspector, which basically runs the inspect function interactively, and can be called from the command line with no interaction. There is also now an RGB color picker, and some bindings to the new highlight_python function (more on that later).

      For some reason my favorite part of this new module is the output of -v:

      Screenshot 2022-05-12 at 23 37 24

    Additions

    • Add Collapsible widget (114da3a3d769d6abd72a8727ed036b1e947c0a23)

    • Add new highlighters module with RegexHighlighter class (7e6cd024739b880aa53ef3b9c2ca9414c15493e9, 6bd3d4a3d7b8be179c4aeb7aa73079a57c29f8b3)

      This class can be used to statically highlight any type of text, combining regex with TIM. Since it's fully based around regex it will never be a full highlighter, a'la Pygments, but I feel like that is outside of the scope of the library. See an example of this in the showcase section.

    • Add is_scroll, is_primary & is_secondary helpers to MouseEvent (522e4dd939c13824b4c6c6bade69ebb8bfdf51bb)

    • Add Terminal.no_record context (b7d4976efc6756548b3903c77b3878f6972b156c)

    • Add WindowManager.alert and WindowManager.float methods (53e9b84c177e24aab3546ab57bfb218274ea06ac)

      The alert function is pretty much the exact same in terms of functionality to the one that came before it, though it's been refactored a bit. The toast method however is completely new to the library, but it's goal and general look & feel come from the Android feature of the same name. I personally think it looks dope, and you catch a glance at it on ptg startup!

    • Add layout assign parameter to WindowManager.add (6c95ac0c416290e810ffa9a012e422d3ca2861bc)

    • Add window manager Layout class (8250d6d7bebe687b53a0ee3e6f7169f2ffa0883d)

      This really is the feature of this update. Essentially, layouts let you define sizes & positions for your windows, which is then continually applied whenever the terminal resizes or windows are removed/added. It also tries to be minimal but expressive in its syntax, and do as many dynamic things as possible.

      For example, take the following code:

       manager.layout = ptg.Layout()
       manager.layout.add_slot("Header", height=5)
       manager.layout.add_break()
       manager.layout.add_slot("Sidebar", width=0.2)
       manager.layout.add_slot("Body")
       manager.layout.add_break()
       manager.layout.add_slot("Footer", height=3)
      

      It creates a 3-row layout. The first row just contains a header with a height of 5, and spanning the entire terminal in its width. The second row contains a sidebar that is 20% of the terminal's width, and a body that fills whatever remaining space it has. Finally, we have a footer, that is 3 characters height and once again spans the entire terminal.

      You may have noticed that the second row had no height definitions whatsoever. This is because the layout can calculate the remaining height for the row based on the slots with static dimensions. In effect, this means that you only need to specify the 'defining dimension' for each slot, and the rest will be calculated by the library. This Dimension system may in the future be extended into the realm of widgets, and I have plans of first adding the ability to nest layouts, and maybe eventually adding a layout-based container widget.

      Screenshot 2022-05-12 at 23 49 27

    Bugfixes

    • Fix overly greedy optimization in MarkupLanguage.parse getting rid of important unsetters (32e30b5e50e5d71f89c2d5a64775820dce805f99)
    • Fix / not being handled properly in various places (2b15e5174582082999352140faafccbe05fa2670, e3e9e87ccb137a378406139e5d1f57c5decb4ce2)

    Showcase

    Screenshot 2022-05-12 at 23 02 27 Screenshot 2022-05-12 at 23 02 55 Screenshot 2022-05-12 at 23 04 02 Screenshot 2022-05-12 at 23 05 36

    Closing thoughts

    That's all for now. Next up should be either a full ScrollView widget that wraps around an inner Container, a more efficient compositing method, a universal & real-life user tested color palette or a combination of all. Since I'm currently quite busy with university I'm not sure when I'll get around to creating a new release, but it shouldn't be too far off.

    As a final note, this release might be the one to push the library over 1000 stars. Thank you to everyone who has ever used PTG, raised an issue or even just checked it out or left a critical HackerNews comment for it. I never imagined my work to become this popular, and I can't wait to see where it ends up.

    Ok, bye

    :rocket:

    Source code(tar.gz)
    Source code(zip)
  • v5.0.0(Apr 19, 2022)

    Pretentious title, I know.

    This version is essentially a rewrite of the window_manager module. There is now better task distribution, things are cleaner, and there is one less 1000+ line module in the library.

    The biggest change was moving all printing logic into a new module compositor. At the moment this does basically the same thing as WindowManager used to, albeit a slight bit more optimized, but in the future implementing a difference-only drawer should be relatively simple.

    The animation system also got completely rewritten. I'm still not fully satisfied with some aspects, but this should be the last API-breaking set of changes done to it for the foreseeable future. The TL;DR of this would be something like:

    • A single Animation base class
    • Looping animations
    • An exposed FloatAnimation that simply transitions its state from 0.0 to 1.0 over the given duration
    • Better logic, usage of elapsed time instead of independent measurements & framerate calculations

    Overall, this release provides much better internal structure and stability, plus some extra features and additions. The upcoming couple of releases will focus more on the feature side of things, but there is at least one similar refactor planned (for the ansi_interface module), though likely involving less API changes.


    Items marked in bold are API breaking changes.

    Refactors

    • Refactor window_manager.py into 3 files under window_manager submodule
    • Refactor the entire animation system (71cf2619baf2885d801bb6ef3bc45b62f3de7dad)
    • Move scrolling behaviour into new ScrollableWidget class (37f8ffae651d7804fac07175901bd3e35aa5baab)
    • Improve Terminal API (d0209fbf2e59950f220375f857baac35e6d7dee3)
    • Rename widgets/layoutswidgets/containers (e06608d4f2ba88216ca73a6fcbd1ddcde62a54c0)

    Additions

    • Add StyleManager.__call__ method that sets the given **kwargs keys and values (2e69cbf27ca235ef958d5ef4d3d62ffda413abd8)
    • Add (currently unused) Widget.get_change helper (48d3e5c78237a7998e93055db0a9b5550b374242)

    Showcase

    As this is an internal refactor based update, there isn't much to showcase. Toggling fullscreen on a Window is now animated, and some other animations are improved.

    Here is a random SVG screenshot.

    screenshot

    Unrelated note on browser rendering oddities HTML engines seem to render `foreignObject` SVG-s just slightly differently to eachother. Here is what the above looks like on Chrome for my machine:

    _Users_lapis_Code_Projects_pytermgui_screenshot svg

    In comparison, my phone's GitHub app tends to render text off the "terminal" panel for some reason, and even the browser tends to render the colored unicode blocks incorrectly, often adding a border around them. Odd!

    Source code(tar.gz)
    Source code(zip)
  • v4.3.2(Apr 9, 2022)

    This release is focused on fixing two bugs, #46 and #42. It also introduces the getch_timeout function, which is pretty neat, though sadly special functionality is limited to POSIX systems.

    Bugfixes

    • Improve how pixel size is received and fix process hanging when the terminal does not support it (49ff24445329e6f3581c1cf34c5265225ef765bd, #42)
    • Fix stream truncation raising an error on Windows (6f304ab3c4e3276f591009fe92b580c01b78dd8a, #46)

    Additions

    • Add getch_timeout method (49ff24445329e6f3581c1cf34c5265225ef765bd)
    Source code(tar.gz)
    Source code(zip)
  • v4.3.1(Apr 3, 2022)

    This release fixes some minor inconveniences that slipped through the last version release.

    Bugfixes

    • Fix #45 by catching errno.EINVAL on stream truncation (f8b1d3f3846dd19fbdad6a064ba1e99e3472e9d3, #45)
    • Fix Container first lines sometimes having wrong indentations in SVG exports (9c32ac9e298786449f101cad8d2664584304ffa7)
    • Fix Helpers app not showing any bindings (61dbed9be42220b96c42eb97105ccda0f2071bc4)
    Source code(tar.gz)
    Source code(zip)
  • v4.3.0(Apr 2, 2022)

    This version improves the Terminal class and gives it some extra abilities, which are then used by some new modules.

    Anything written to the terminal can now be recorded by it, simply using the terminal.record context manager. This will then give you a new Recorder instance, which contains all the data written to the terminal in the context. This can then be exported to static HTML, or even a terminal-mimicking SVG!

    The recording and subsequent outputs also respect positional printing, thus your screenshots will be accurate regardless of what weird thing you might be doing. Other than the extra functionality mentioned above, this release was a great stress-test for TIM and related utilities, and a lot of minor but important improvements have been made during the process.

    Additions

    • Re-introduce Helpers ptg app (ac5687076507dc2fdb7ab6f87a71a48fc00dcd70)
    • Add F-keys to input.keys (5157546c9c9729266b1744321fa2b155f14bf9a4)
    • Add terminal Recorder class, ability to record anything written to the terminal using a context (b8c49e0ec823afbdfc9d0b31758055316abb6657)
    • Add Color.hex property (ffbb4567ab65e8d2c9c3c691628419e1925135f1)
    • Add Color default fore & background setter and getters, using the terminal’s palette (5b2c4a3ff9ef586a19c709def766d082adaeda8b)
    • Add LINK and POSITION TIM token types (309e30171084a06a424d6562a3f72585eca8d73b, 401aad8d19da6fb3f70be70f170817726c728a37)
    • Add exporters module to generate HTML pages and SVG screenshots from any terminal content (a01a6f8670dc2ecc8e4860b423ffc9a1bba012a4, d6060d5ffe042ae76c2867cf139ecc2fc2e869b7, cd69680cd01e55bed3ac4e0f6dc8b0cfd9f9572a)
    • Add style construction argument to Label (9f7336eb31a8052827beff460ee6d2dd6dc24a45)
    • Add tim.get\_styled\_plains method (8c05e69c82925f08c2a6f0b559d52dd8154d3e15)

    Refactors

    • Slightly optimize how WindowManager.print works (99bad926f9cd44c3610acbe7dea1d008cce50315)
    • Move regex-related utilities into regex.py (e8befc10b97109edbc1a35b0f1bfdcfe550992bf)

    Showcase

    These screenshots are all directly coming from PTG, and are not actual native screenshots taken by the operating system.

    recording screenshot pagoda

    Source code(tar.gz)
    Source code(zip)
  • v4.2.1(Mar 22, 2022)

    This version implements a new, more accurate and less gray-biased color distance algorithm. It also introduces @lru_cache usage, thereby increasing the performance quite a bit.

    Refactors

    • Improve color degradation & caching (7bd802892c7896d3f5345af2d05aab35ff4fb246)

    Showcase

    Source code(tar.gz)
    Source code(zip)
  • v4.2.0(Mar 21, 2022)

    This version adds graceful color degradation, which (to my knowledge), makes us one of the first terminal libraries to do so, but definitely the first in our specific niche!

    This is all done automatically, using the newly-rehomed Terminal class and its instance. Essentially, every time a color is created through TIM, the new str_to_color method is called, which will by default localize all output colors. During this localization the xterm-standard HEX value for the given color is found, and that is then used to create a new color in the terminal's color space.

    For example, lets say you have an RGB color of 000;111;222, but your terminal only supports the xterm-256 palette. PyTermGUI will, under the hood, determine the RGB value of this color, and get the weighted difference between it and and all known palette colors. Once that is done it will find the closest match, create an IndexedColor with the newly found index and return that back to TIM.

    Now this all sounds very computationally complicated, which it is. Thus, there are a couple of simple "caches" inside the new colors module. The first one caches all input given to str_to_color with its corresponding output, and the second one saves all input and output of the aforementioned color matching. Because of this, my machine shows only a sub-1 ms difference of frametime parsing a true-color and 16-color representation of the same, complicated markup frame (namely, ptg -m).

    Additionally, there is now a really robust implementation of the https://no-color.org standard! Unlike pretty much all modules, we don't just completely omit colors, rather we calculate each color's brightness and then assign a value to them in the xterm-256 greyscale range, thereby retaining most of the contrast, the ability to set background colors and more. You can see some demos of this further down the page.

    Additions

    • Add a graceful degradation Color layer (5053603026289d784dd9136c7114606e258c3e4e)
    • Expose color support in terminal (f26580732923fc71cded2347acafc1830d2e84c0)
    • Add support for prettifying UserDict and UserList (35e789c978b51b37d70f89c3f455314bc8f36314)
    • Add support for NO_COLOR using greyscale ramps (0cdf71209ac6f46fba28dc52729fbfae1e4e2da4)
    • Add colors module with color types for all terminal colors (f26580732923fc71cded2347acafc1830d2e84c0)

    Refactors

    • Move terminal to its own module (5aeb397c0f9037a3338d76e554795e7c2d23be30)

    Bugfixes

    • Fix [ sometimes being ommitted during prettify_markup (a2defd8f486371ee993bce689e697787a03563b2)

    Showcase

    The same HSL to RGB color palette printed by TIM, with only terminal.forced_colorspace being changed between runs.

    Screenshot 2022-03-21 at 18 17 36

    ptg ran with NO_COLOR=1 as an environment variable.

    Screenshot 2022-03-21 at 19 32 54

    Source code(tar.gz)
    Source code(zip)
  • v4.1.0(Mar 16, 2022)

    This update is focused on the brand-spanking new StyleManager API. Previously, styles were "managed" as a single dictionary, which while simple and robust, was very limited, ugly and in general not the best. This was a leftover design decision from even before TIM was an idea, just to put its age into perspective.

    The new API allows users to use JS-like dotted syntax, such as Container.styles.border = "60 bold" to achieve what was previously Container.set_style("border", MarkupFormatter("[60 bold]{item}"). As you could notice, the given values are also much simpler now: Anything that is not already a StyleCall will be converted into one, and if the passed value was a string with no valid markup it will be parsed into [{{passed_value}}]{item}. You can also set multiple styles at one time, using "__" (double underscore) character to separate them.

    Getters are also the same way. Instead of a private Container._get_style("border") call, one can now use Container.styles.border. It also returns an already instantiated StyleCall, unlike the previous API which created them on every new call.

    Best of all, the old API remains to work! I wouldn't bet on this continuing forever, so all new code should be written using the new version. If it does ever get removed I'll be sure to make it very obvious and loud.

    Refactors

    • Implement new StyleManager class & API (e4c0036c4546c10289c62a65fa1d6d7fe085cebb)
    • Improve Container.debug to shorten itself & use type(self) (e8ccd35d67f1bad22caf39f0c870436f87b7fa89)

    Additions

    • Add value readout to ptg -g (a86e5915bf34a9d237136df77af92b05016b8d48)

    Bugfixes

    • Fix ESC not being outputted in ptg -g (661e5ce818d3a170012c6c039fb1690598280693)

    Source code(tar.gz)
    Source code(zip)

  • v4.0.1(Mar 13, 2022)

    There happened to be some minor issues in the previous version, but they should be fixed now.

    Bugfixes

    • Fix broken macro call in Markapp (524d9199a5bd026b44bb37f35f2f7cc621221c08)
    • Fix string literals not being displayed correctly in inspect (418812492e298f0e5fbce2122f72561afd215d10)

    Additions

    • Expose inspect-identifier markup alias (319be785350a76ff1742002dc83820f5eb9d30ac)
    Source code(tar.gz)
    Source code(zip)
  • v4.0.0(Mar 12, 2022)

    This release focuses on the brand new inspector capabilities of the module. More information about them can be found in the inspector documentation.

    Items marked in bold are API breaking changes.

    Additions

    • Introduce new Inspector widget and inspect helper function
    • Add Container.lazy_add method to expose _add_widget(..., run_get_lines=False)

    Refactors

    • Move prettify to new submodule prettifiers & improve its behaviour
    • Move is_interactive under terminal
    • Remove MarkupLanguage context manager in favor of aprintmethod
    • Refactor MarkupLanguage.pprint

    Fixes

    • Fix support for aliasing to an existing tag
    • Fix blocking getch call on Windows

    Showcase

    Screenshot 2022-03-12 at 15 41 48

    Screenshot 2022-03-12 at 15 43 12

    Source code(tar.gz)
    Source code(zip)
  • v3.2.1(Mar 7, 2022)

    This release is mostly for fixing a couple of annoying issues that came up in the last release, as well as to update the README. The biggest new "change" is the introduction of TIM, PyTermGUI's markup language. It stands for Terminal Inline Markup, and is analogous to the previous markup name (so much so that the latter is still provided as a reference to the same instance).

    Refactors

    • Rename markuptim, but keeping the original name for backward-compatibility (aa79c43fee45634022dec8e47f1e9f5ed79556e9)
    • Rename animatorsanimations, expose Animation and CustomAnimation classes (12f53ddfbddea21158e21263c61a906735729b01)
    • Update & Improve README

    Bugfixes

    • Fix TIM macros not being colored correctly in MarkupLanguage.prettify_markup (aa79c43fee45634022dec8e47f1e9f5ed79556e9)
    • Fix ptg --version not functioning on PyPi installs (e27185779c8e28928acbd0d8352f5735414f22e1)

    :moon:

    :rocket:
    :fire:

    Source code(tar.gz)
    Source code(zip)
  • v3.2.0(Mar 4, 2022)

    Edit:

    ptg -v does not work on PyPi installs in this version. This was already fixed in (e27185779c8e28928acbd0d8352f5735414f22e1), but I didn't deem that one fix to be worthy of a full bugfix patch.


    This version mostly focused on adding some nice utilities while improving the old ones. Before that however, I want take a second to mention how the library grew almost 300 stars in 2 days. I am immensely grateful for the exposure my project is getting, and I can't wait to see it in the wild!

    Things to point out:

    • Improvements to pretty printing in general
    • pretty module: This is a very simple module that allows setting up displayhook with only one line in the REPL
    • KeyboardButton widget: This allows keyboard mnemonics inside PTG.
    • !rainbow and !gradient macros: These are very pretty and fancy looking.

    Refactors

    • Colorize version info (b3075a3b6b4ef481e4c5353ce523f806ec9376ce)
    • Stop displaying version hash info if it could not be found (695511610df6dce9c18bb7e105422d0dbd304b72)
    • Improve parser documentation (933729e98142039ae601bc3eecebfb60e39882db)
    • Extend pretty printing to more data types (d0ae9ccbb4a7c5130f55751036e02d3a9e5b606a)
    • Improve IPython display hook support (caa7c748f51019166b01ea163cb6d2f77fb537b5)

    Bugfixes

    • Fix redundant sequence output in MarkupLanguage.parse (7f49087a747fb3d7189f09a598c29313c340e1cc)
    • Fix markup macros only running once due to caching (a2edf6da110bc229e423793fed2153f6b911cb3e)
    • Fix Window.is_modal not being applied properly since a mouse handling refactor (c1d36190d20cbcefcae8c91181d2d2d4de37c269)

    Additions

    • Add KeyboardButton widget (a1a0dadfb6243981c2a7bdd4f57048a87c41bef0, c495dd0d4d6a173a2ad9e031d003a17eb080123d)
    • Add non_first_padding to Label (c630e6f9aff2dbc688197ab9866657ef04d70f8b)
    • Add ability to set box in Container constructor (88536be5035e83ed7ad4c4b2de4980bd2c85a559)
    • Add pretty module for quick displayhook setup (48fb0dfde9742328603e26950deca657ad483299)
    • Add !rainbow and !gradient macros (bc0e0911a14922111a429aa153e4ebc8ff4aa394)

    Screenshot 2022-03-04 at 14 46 10 Screenshot 2022-03-04 at 14 45 06

    Source code(tar.gz)
    Source code(zip)
  • v3.1.0(Feb 27, 2022)

    This is a relatively minor release, mostly focused on the new pretty-printing functionality. I wanted to release this before the next major update, as that may take some time and these features are really useful in their own right.

    The new MarkupLanguage.prettify method is quite customizable: It allows you to customize all of the builtin styles it uses, as well as set indentation count, force ANSI sequences to be displayed as markup or force data-structures to be displayed flat (condensed). The default style looks really good in my opinion, and it should be a very useful tool.

    Obviously, the idea was inspired by Rich's implementation of the same concept, but I tried to fix all my grievances with that version.

    Additions

    • Add Terminal.pixel_size attribute (6e350b182849a7ba062c97aa1a55628f5c9e78cd, ce27e3cde131e66a99085cc58ba7cf39f7bb14c8)
    • Add prettify_ansi,pprintandsetup_displayhook()methods toMarkupLanguage`` (5bdf6177b28eb7fcd6475ee1b402b6b79eb671ba)

    Bugfixes

    • Fix starting state not being reverted after animation finish (#38, 135a5bf553e0281a39f8318c48cffe15198426f3)

    Showcase

    Here is a quick demo of some of the prettifying functionality.

    Screenshot 2022-02-27 at 12 14 28

    Source code(tar.gz)
    Source code(zip)
  • v3.0.0(Feb 22, 2022)

    This version mostly focused on improving already built features, but there is a lot of important additions as well.

    The most notable new change would probably be the PixelMatrixclasses. These allow you to display an arbitrary matrix of pixels as a widget. DensePixelMatrix scales the entire widget down by a factor of 4 (in normal PixelMatrix, every pixel is made up of 2 block characters. In DensePixelMatrix all pixels make up only half a block.

    This would normally not constitute for a major release, however the Slider refactor forced our hand. Some parts of its API have changed, though mostly for the better.

    Items marked in bold are API breaking changes.

    Refactors

    • Refactor Slider widget (788a709e2a3326fb725bf8600aa3d208a12b5874, #9)
    • Update Button default chars (f370deaedd88f52c5008fcfe0a5ff1ae7efdf2c9)
    • Change WindowManager.framerate 120 -> 60 (320d65c1c6988a727e724674d7dd16da0d8dcc5c)

    Additions

    • Add MarkupLanguage.prettify_markup (d6733f5dc02817e8be1cadde17f2bb9ee94a4b94)
    • Add WindowManager.nullify_cache & Window.nullify_cache (814d2055e89e40256fea1e9f9e7d7347b697c0f7)
    • Add !link markup macro (0c05080928a5e9a6e65ba3d4148e0b794b556852)
    • Add StyledText class (be2f5dec466d84458e376af5ea7e428920733247)
    • Add ColorPicker widget, CLI app (5a09f43b950414e231ac0ebf85f5db17499d3785, 45b6d02d46c3eea30b2c4cabb96cd08cff3f688a)
    • Add PixelMatrix & LargePixelMatrix widgets (84312c16a399c9e58c070c04d23d397610895aca)

    Bugfixes

    • Fix selection lingering after mouse event (2a0b79b720c8a1522a66a92d611fdfa95276301b)
    • Fix Right-click release events being misdetected (1b7b69a55a6c006991f333f266757b1a3d153f4a)
    • Fix Window._auto_min_width disregarding sidelength (8b51ff0822f8e471f55bfeb1186fb8659cfd543f)
    • Fix incorrect behaviour in Container._update_width (363093aa3812bad4bb92250c7900a0f9d7258f80)

    https://user-images.githubusercontent.com/66030897/155183664-4d42c693-b5f1-474f-9b15-d9fd477833f2.mov

    Source code(tar.gz)
    Source code(zip)
  • v2.2.0(Feb 14, 2022)

    Version 2.2.0

    This version brings an implementation of animations to the library. The new Animator class is tasked with controlling & updating a list of Animation instances. Animations work using time-elapsed since instantiation, and animate an integer field going from one value to another.

    Refactors

    • Make Container._centered_axis public (0304aca4b94517648b46bcf68e3ae4a18f1e0b68)
      • Note: This is not deemed API breaking, as this attribute was never meant to be user facing.

    Fixes

    • Fix Overflow.HIDE only hiding entire widgets (4289a5c6bd5df535a43053173179bc9f3ec0526f)
    • Fix getch application growing in height indefinitely (ea5b721248f6c599a6c795a34bd1dae5608eb565)

    Additions

    • Add Animator class (c87586f40bafcd88c557abd41691c898bb74caaa, ceb030d96269ebf8a8898c8969df13a85ac55704)

    Showcase

    Here is a showcase of the already-implemented animations in WindowManager, using the ptg CLI environment.

    https://user-images.githubusercontent.com/66030897/153866607-61f3682c-5f23-47f1-a998-b544b83f113f.mov

    Source code(tar.gz)
    Source code(zip)
  • v2.1.1(Feb 11, 2022)

    Version 2.1.1

    This release fixes various issues related to Windows systems. It also brought about a more logical refactor for WindowManager.process_input.

    As this is a minor release, not much has changed. To see the bigger changes that have recently happened, see the previous release.

    Items marked in bold are API breaking changes.

    Fixes

    • Fix CTRL_C not being captured on Windows machines (01139633c52c07d14e15e4f1fef1ba638a06df35)
    • Fix widgets/interactive.py not being packaged (ea78b126c4d3ae3dcb6aca8a446b852a62f510cc)
    • Silence keys attribute errors (75cebf715a74c4bba9963bc6be8d870a09f7af2c)
    Source code(tar.gz)
    Source code(zip)
  • v2.1.0(Feb 11, 2022)

    Version 2.1.0

    This update is mostly focused on bug fixes, but also has some additions. The library should now actually install on Windows machines, which is pretty dapper.

    Items marked in bold are API breaking changes.

    Removals

    • Remove broken SIGWINCH monitor (#25, #19)

    Additions

    • Add Container.scroll and Container.scroll_end helpers (0119e31dccb600eea8e3d6ad83114ea051316bf9)
    • Add SINGLE box type, rename old SINGLE box to ROUNDED (5dda72793644f5144daccbc7d7772771e91afb7e)

    Fixes

    • Fix some issues with InputField (0920ffc1064db262b333855a856e9ac112ba3d4f)
    • Improve how terminal resize events are handled (7143affeeac691eeee23c130fb45686b47e2213a)
    • Fix 1 char offset in non-Container widget widths (e3ac8d74bbbfb3fba9d4f87a6cd0ff7d225712d8)

    Showcase

    Here is an image of my first major project with the library, Pagoda. Screenshot 2022-02-11 at 9 48 03

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0(Jan 25, 2022)

    Version 2.0.0

    This version contains a whole lot of nice Quality of Life changes, as well as some major additions. The highlights would probably go to Container-s now having native support for scrolling their contents, a brand-spanking new and hugely improve mouse input API, and improved documentation.

    Items marked in bold are API breaking changes.

    🔧 Fixes

    • Fix widget height not following its destiny sometimes
    • Fix Splitter inner widget positioning

    🔃 Refactors

    • Restructure widgets module
    • Change to Google docformat
    • Rewrite Container.get_lines for brevity, efficiency and more features

    ➕ Additions

    ➖ Removals

    • Remove redundant _SYS_HAS_FRAME in ansi_interface

    Showcase

    Here is a quick clip showcasing some of the new features.

    https://user-images.githubusercontent.com/66030897/151056702-6708eea1-db1d-43dd-9cab-4825bb017d80.mov

    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Jan 9, 2022)

    Fixes

    • Fix SIGWINCH on Windows (#6)
    • Fix an error with empty markup tags

    New additions

    • Add InputField expect attribute
    • Add overline capability (#7, thanks to @rbanffy)
    • Add --version flag to CLI
    • Add context management to MarkupLanguage
    Source code(tar.gz)
    Source code(zip)
  • v1.0.1(Jan 2, 2022)

    This is quite embarrassing. Guess who forgot to change relative image links to be accessible on other sites?

    Well, it's been fixed now.

    Ok, bye 🚀

    Source code(tar.gz)
    Source code(zip)
Owner
super frictionless workflow.
null
A simple, yet powerful web GUI to manage your Wireguard server, powered by Flask.

Linguard Linguard aims to provide a clean, simple yet powerful web GUI to manage your WireGuard server, and it's powered by Flask. Read the docs for f

Jose Antonio Mazón San Bartolomé 111 Jan 7, 2023
Textual is a TUI (Text User Interface) framework for Python inspired by modern web development.

Textual is a TUI (Text User Interface) framework for Python inspired by modern web development.

Will McGugan 17.1k Jan 8, 2023
Kivy is an open source Python framework for creating cross-platform multi-touch mobile applications with Natural User Interface.

Kivy is an open source Python framework for creating cross-platform multi-touch mobile applications with Natural User Interface.

Grace Ugochi Nneji 3 Feb 15, 2022
This simple python program can be used to make FontChooser dialog in Tkinter Applications.

tkFontBox This simple python program can be used to make FontChooser dialog in Tkinter Applications. how to use? Copy the tkFontBox.py file into your

Pawan Kumar Prachi 1 Feb 8, 2022
Dear PyGui: A fast and powerful Graphical User Interface Toolkit for Python with minimal dependencies

(This library is available under a free and permissive license however, if you Enjoy Dear PyGui please consider becoming a Sponsor) Dear PyGui is a si

Jonathan Hoffstadt 9.4k Jan 4, 2023
Dear PyGui: A fast and powerful Graphical User Interface Toolkit for Python with minimal dependencies

(This library is available under a free and permissive license however, if you Enjoy Dear PyGui please consider becoming a Sponsor) Dear PyGui is a si

Jonathan Hoffstadt 9.4k Jan 7, 2023
pyglet is a cross-platform windowing and multimedia library for Python, for developing games and other visually rich applications.

pyglet pyglet is a cross-platform windowing and multimedia library for Python, intended for developing games and other visually rich applications. It

null 1.3k Jan 1, 2023
Make desktop applications using HTML and CSS with python

Neutron Make desktop applications using HTML and CSS with python What is Neutron Neutron will allow developers to design modern applications in python

Ian Baldelli 284 Dec 29, 2022
Python code examples on how to create several applications using Dear PyGui.

Python code examples on how to create several applications using Dear PyGui. Includes building and editing a table, as well as visualizing sorting algorithms in a plot.

Alexander H. 7 Sep 15, 2022
A library for building modern declarative desktop applications in WX.

re-wx is a library for building modern declarative desktop applications. It's built as a management layer on top of WXPython, which means you get all the goodness of a mature, native, cross-platform UI kit, wrapped up in a modern, React inspired API.

Chris 115 Dec 24, 2022
An qt asset browser for applications like houdini/nuke/maya/blender

AssetBrowser A qt asset browser for applications like houdini/nuke/maya/blender Currently in development Note: Only houdini plugin available during de

Jonas Sorgenfrei 6 Aug 5, 2022
Key Cast - Cast your key presses and mouse clicks on the screen, while casting your favorite application on the screen. Better than the rest.

Key Cast Screen cast your keyboard and mouse clicks in style Project Homepage » View Demo · Report Bug · Request Feature Table of Contents Introductio

Mehul Singh Teya 13 Dec 23, 2022
🧮A simple calculator written in python allows you to make simple calculations, write charts, calculate the dates, and exchange currency.

Calculator ?? A simple calculator written in python allows you to make simple calculations, write charts, calculate the dates, and exchange currency.

Jan Kupczyk 1 Jan 15, 2022
A simple one-line quick entry GUI for your Obsidian daily notes in markdown format.

Quick-note-entry-for-Obsidian A simple one-line quick entry GUI for your Obsidian daily notes in markdown format. Log your day quickly with this simpl

Adrian Papineau 22 Oct 4, 2022
Open source UI framework written in Python, running on Windows, Linux, macOS, Android and iOS

Kivy Innovative user interfaces made easy. Kivy is an open source, cross-platform Python framework for the development of applications that make use o

Kivy 15.4k Jan 7, 2023
Delphi's FireMonkey framework as a Python module for Windows, MacOS, Linux, and Android GUI development.

DelphiFMX4Python Delphi's FireMonkey framework as a Python module for Windows, MacOS, Linux, and Android GUI development. About: The delphifmx library

Embarcadero Technologies 191 Jan 9, 2023
Build GUI for your Python program with JavaScript, HTML, and CSS

https://pywebview.flowrl.com pywebview is a lightweight cross-platform wrapper around a webview component that allows to display HTML content in its o

Roman 3.3k Jan 1, 2023
Create shortcuts on Windows to your Python, EXE, Batch files or any other file using a GUI made with PySimpleGUI

shor Windows Shortcut Creation Create Windows Shortcuts to your python programs and any other file easily using this application created using PySimpl

PySimpleGUI 7 Nov 16, 2021
A system tray application written in python that will assist you with your keyboard endeavors.

A system tray application written in python that will assist you with your keyboard endeavors. It has features such as abbreviation, email autofill, media control, writing from clipboard ,typing current date and time etc.

Mach50 1 Dec 15, 2021