Coder Social home page Coder Social logo

bczsalba / pytermgui Goto Github PK

View Code? Open in Web Editor NEW
2.2K 20.0 53.0 54.9 MB

Python TUI framework with mouse support, modular widget system, customizable and rapid terminal markup language and more!

Home Page: https://ptg.bczsalba.com

License: MIT License

Python 99.69% Shell 0.21% Makefile 0.09%
python3 python typing tui terminal ansi-escape-sequences ansi-escape-codes gui pytermgui cross-platform

pytermgui's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pytermgui's Issues

[REQUEST] Add unit testing

Planned

  • file_loaders.py & serializer.py --> test_dump_n_load.py
  • parser.py --> test_parser.py
  • animations.py
  • enums.py
  • ansi_interface.py
  • exceptions.py
  • helpers.py
  • input.py
  • inspector.py
  • window_manager.py
  • widgets

Not testable / Not needed

  • context_managers.py
  • pretty.py
  • cmd.py

[BUG] not possible to resize window from the left side

Describe the bug
Dragging left side of window moves right side of window, which might make it disappear completely.

To Reproduce
Steps to reproduce the behavior:

  1. Click left side of window border
  2. Drag it
  3. The right side of window will try to follow the mouse cursor
  4. If you drag it to the left, window will implode on itself and disappear

Expected behavior
Clicking on the left side of the window should activate resize on the left side of the window, while the right side remains still.

System information
PyTermGUI v1.1.0
Python: 3.10.1
Platform: Linux-5.15.11-200.fc35.x86_64-x86_64-with-glibc2.34
Git commit: e061977

Possible cause
Lack of testing all possible ways a window can resize?

[BUG] Focus next doesn't work

focus_next method doesn't work
Cycles on the first and last windows.

To Reproduce
Steps to reproduce the behavior:

  1. Create layout with 3 windows
  2. Bind key to manager to self.focus_next()
  3. run program
  4. press tab

Should cycle through all windows

System information

PyTermGUI version 6.0.0
 
System details:
    Python version: 3.10.4
    $TERM:          st-256color
    $COLORTERM:     None
    Color support:  ColorSystem.STANDARD
    OS Platform:    Linux-5.17.5-arch1-1-x86_64-with-glibc2.35

Possible solution

def focus_next(self):
        if self.focused is None:
            self.focus(self._windows[0])
            return self.focused

        self._windows = self._windows[1:] + [self._windows[0]]
        self.focus(self._windows[0])

        return self.focused

[BUG] Slider doesn't handle resizing properly

Describe the bug
When resizing a window or container with a Slider inside, the Slider will only update its line length after the second update, causing it to raise a LineLengthError.

To Reproduce

  1. Create a Window
  2. Add a Slider
  3. Resize window to become smaller

Expected behavior
The slider should update its width.

System information

PyTermGUI v1.0.1
Python: 3.9.9
Platform: macOS-12.0.1-arm64-arm-64bit
Git commit: ec879a5

Possible cause
The Slider.get_lines method doesn't properly handle resizing.

[BUG] Screen updates cause lots of scrollback buffer to be created

Describe the bug
Screen updates, such as animations, produce lots of output in the scrollback buffer.

To Reproduce
Perform almost any action in pytermgui application and notice how the scrollbar gets really large, and you can in fact scroll back to see the history of what the screen looked like. This was done with iTerm2.

Expected behavior
Most ncurses based applications do not seem to spam the scrollback buffer this much.

System information
This is on macos Monterey with iTerm2. Running python inside of docker.

PyTermGUI version 6.1.0

System details:
    Python version: 3.9.10
    $TERM:          xterm
    $COLORTERM:     None
    Color support:  ColorSystem.STANDARD
    OS Platform:    Linux-5.10.104-linuxkit-x86_64-with-glibc2.31

[BUG] 6.0.0 no longer has smooth borders by default

I've just started with this, so the extent of the code I have is basically just the manager, a layout, and a single window within that layout. Before updating to 6.0.0, the window had the default smooth borders you see in all of the screenshots. After updating, the border is now made up of regular characters.

Just to test, I tried removing the layout and doing things basically exactly as the documentation states, and still have the same issue. I don't believe this was intentional, I didn't see anything about it in the changelog.

[BUG] Documents at https://ptg.bczsalba.com/pytermgui.html seem broken or outdated

Describe the bug
I'm trying to walk through the example given here: https://ptg.bczsalba.com/pytermgui.html#combining-our-knowledge-to-create-an-application (and in earlier examples) and they all seem to have odd errors in them.

For example, the first sample code listed has:

import pytermgui as ptg

with ptg.WindowManager() as manager:
    window = ptg.Window(
        "[wm-title]My first window!",
        "",
        ["Exit", lambda *_: manager.exit()],
    )

    manager.add(window)
    manager.run()

Hitting the "Exit" button when running this app throws an exception as there is no 'exit()method on theWindowManager` class. This is fairly easy to fix, but the later example (at the link above) doesn't work in non-obvious ways.

To Reproduce
Steps to reproduce the behavior:
using pytermgui 5.0.0 on linux in a RoxTerm window. Run the above program. Click on the "exit" button

Expected behavior
Program should exit cleanly for the exit() case. The example code should run in the namespace.yaml case.

System information
pytermgui 5.0.0
Ubuntu 20.04
Roxterm 3.12.1 (just tested in "Terminal" which ships with Ubuntu 20.04 - same results)

Add the output of "ptg --version" in this box.
pyTermTk on  main [?] via 🐍 pyenv 3.10.4:pytermtk took 2s ➜ pip freeze
pytermgui==5.0.0
PyYAML==6.0
pyTermTk on  main [?] via 🐍 pyenv 3.10.4:pytermtk ➜ ptg --version
^[[4;1320;940tfatal: Needed a single revision
PyTermGUI v5.0.0

Python: 3.10.4
Platform: Linux-5.13.0-40-generic-x86_64-with-glibc2.31
pyTermTk on  main [?] via 🐍 pyenv 3.10.4:pytermtk ➜ 1320;940t

Note that there is a "fatal" line in the output and that it leaves the terminal with garbage characters.

Possible cause

Possible solution

Seems like some of the documents are out of date, but there also seems to be a different problem.

[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.

[REQUEST] Consider implicitly including terminal coordinate system origin in cursor movements

Is your feature request related to a problem? Please describe.
When using any of the cursor-moving API (such as cursor_at, terminal.print(..., pos=...) and others) the user has to manually include the terminal origin to get the desired result. This could, and should just be done implicitly by the library.

Describe the solution you'd like
All of these methods should just include the origin by default. It would be ideal for them all to call a central function that does it this way, which would perfectly coincide with my desires to separate ansi_interface functionality into its own unit, including a class and instance for the terminal's cursor. This could then just be called with a position (such as ptg.cursor.move(pos)), and that action would just include the origin.

Additional context
s/o to #55 and #53 for exposing this issue, both started by the now very important library tester @leftbones.

[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?

Render plot correctly

I'm looking to create multiple plot trend lines inside of a tui.

Another library I'm utilizing produces a string such as
'⠀⠀⠀⠀⢠⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⡆⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀\n⠀⠀⠀⠀⡸⡇⠀⠀⠀⠀⠀⠀⠀⠀⢠⢳⠀⠀⠀⠀⠀⣧⠀⠀⡤⡄⠀⠀⠀⠀\n⠀⠀⠀⢀⠇⡇⠀⠀⠀⠀⠀⠀⠀⠀⢸⠘⡄⠀⠀⡀⢠⢻⠀⢀⠇⡇⠀⢀⠀⠀\n⡆⠀⢀⠎⠀⢣⠀⠀⠀⠀⠀⠀⠀⠀⡜⠀⡇⠀⠀⡇⢸⢸⠀⢸⠀⢇⠀⢸⠀⠀\n⢣⠀⡸⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⢇⠀⢰⢇⢸⠈⡆⢸⠀⢸⠀⡿⡀⠀\n⢸⠀⡇⠀⠀⢸⠀⢀⠤⡆⠀⠀⠀⢸⠀⠀⢸⠀⢸⢸⢸⠀⡇⡎⠀⢸⠀⡇⡇⠀\n⠘⣼⠀⠀⠀⢸⠀⢸⠀⢱⠀⠀⠀⡎⠀⠀⢸⠀⢸⢸⢸⠀⡇⡇⠀⢸⢠⠃⡇⢀\n⠀⠇⠀⠀⠀⢸⠀⡎⠀⠘⡄⠀⢸⠀⠀⠀⠘⡄⡜⢸⢸⠀⢣⠇⠀⢸⢸⠀⡇⢸\n⠀⠀⠀⠀⠀⢸⠀⡇⠀⠀⡇⠀⡇⠀⠀⠀⠀⡇⡇⠸⡇⠀⢸⠀⠀⠀⣿⠀⢣⢸\n⠀⠀⠀⠀⠀⢸⠀⡇⠀⠀⢸⢰⠁⠀⠀⠀⠀⡇⡇⠀⡇⠀⠀⠀⠀⠀⡇⠀⢸⢸\n⠀⠀⠀⠀⠀⠸⣰⠁⠀⠀⠀⠇⠀⠀⠀⠀⠀⢳⠁⠀⠇⠀⠀⠀⠀⠀⠁⠀⢸⢸\n⠀⠀⠀⠀⠀⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡸\n⠀⠀⠀⠀⠀⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡇\n⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇\n⠀⠀⠀⠀⠀⠀⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠃'

When printed from the python interpreter this formats correctly

⠀⠀⠀⠀⢠⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⡆⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⡸⡇⠀⠀⠀⠀⠀⠀⠀⠀⢠⢳⠀⠀⠀⠀⠀⣧⠀⠀⡤⡄⠀⠀⠀⠀ ⠀⠀⠀⢀⠇⡇⠀⠀⠀⠀⠀⠀⠀⠀⢸⠘⡄⠀⠀⡀⢠⢻⠀⢀⠇⡇⠀⢀⠀⠀ ⡆⠀⢀⠎⠀⢣⠀⠀⠀⠀⠀⠀⠀⠀⡜⠀⡇⠀⠀⡇⢸⢸⠀⢸⠀⢇⠀⢸⠀⠀ ⢣⠀⡸⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⢇⠀⢰⢇⢸⠈⡆⢸⠀⢸⠀⡿⡀⠀ ⢸⠀⡇⠀⠀⢸⠀⢀⠤⡆⠀⠀⠀⢸⠀⠀⢸⠀⢸⢸⢸⠀⡇⡎⠀⢸⠀⡇⡇⠀ ⠘⣼⠀⠀⠀⢸⠀⢸⠀⢱⠀⠀⠀⡎⠀⠀⢸⠀⢸⢸⢸⠀⡇⡇⠀⢸⢠⠃⡇⢀ ⠀⠇⠀⠀⠀⢸⠀⡎⠀⠘⡄⠀⢸⠀⠀⠀⠘⡄⡜⢸⢸⠀⢣⠇⠀⢸⢸⠀⡇⢸ ⠀⠀⠀⠀⠀⢸⠀⡇⠀⠀⡇⠀⡇⠀⠀⠀⠀⡇⡇⠸⡇⠀⢸⠀⠀⠀⣿⠀⢣⢸ ⠀⠀⠀⠀⠀⢸⠀⡇⠀⠀⢸⢰⠁⠀⠀⠀⠀⡇⡇⠀⡇⠀⠀⠀⠀⠀⡇⠀⢸⢸ ⠀⠀⠀⠀⠀⠸⣰⠁⠀⠀⠀⠇⠀⠀⠀⠀⠀⢳⠁⠀⠇⠀⠀⠀⠀⠀⠁⠀⢸⢸ ⠀⠀⠀⠀⠀⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡸ ⠀⠀⠀⠀⠀⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡇ ⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇ ⠀⠀⠀⠀⠀⠀⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠃

However, when added to a pytermgui widget it does not render correctly.

Is there any easy way to overcome this?

Also -- thank you for sharing your library, it really is awesome.

[BUG] size has no effect when creating a terminal and recording?

Describe the bug
See #67 (same 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))

I can't seem to get the desired size for the generated SVG. It seems it uses my actual terminal size (vertical screen) rather than what I'm providing using the size parameter (zoomed out to see the full size):

pytermgui2

Expected behavior
Respect the size value of the terminal when exporting a record to SVG.

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

AttributeError: module 'signal' has no attribute 'SIGWINCH'

This module looks really cool, but running the example program (the one from README.md) gives the error,

AttributeError: module 'signal' has no attribute 'SIGWINCH'

I'm on Windows, which seems like it could be related, but README.md says it supports windows. Any ideas? TIA!

[BUG] SIGINT exits leave terminal in dirty state

Describe the bug
When sending SIGINT (ctrl-c) to exit ptg the terminal continues to capture mouse input until the reset command is issued.

To Reproduce

  1. Install pytermgui
  2. Run ptg
  3. Exit with ctrl-c
  4. Push mouse buttons

Expected behavior
Mouse events are not captured.

Screenshots
ASCII cast here

System information

$ ptg --version
PyTermGUI v1.1.0
Python: 3.9.2
Platform: Linux-5.10.0-10-amd64-x86_64-with-glibc2.31
Git commit: 47bed90

[BUG] Missing dependency

Describe the bug
package PyYAML is used in file_loaders.py but it's not listed as its dependencies.

To Reproduce
Steps to reproduce the behavior:

  1. Fresh install python 3
  2. Install pytermgui via pip
  3. Clone repo and navigate to the examples directory
  4. run krm

Expected behavior
There should be no error.

Screenshots

This ain't no screenshot but I think it's more helpful.

Traceback (most recent call last):
  File "/home/pomp/.local/lib/python3.10/site-packages/pytermgui/file_loaders.py", line 138, in <module>
    import yaml
ModuleNotFoundError: No module named 'yaml'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/media/pomp/data/projects/setup/./setup.py", line 97, in <module>
    main()
  File "/media/pomp/data/projects/setup/./setup.py", line 93, in main
    entry()
  File "/media/pomp/data/projects/setup/src/entry.py", line 8, in entry
    show_main_menu()
  File "/media/pomp/data/projects/setup/src/ui/show_main_menu.py", line 87, in show_main_menu
    with ptg.WindowManager() as manager:
  File "/home/pomp/.local/lib/python3.10/site-packages/pytermgui/window_manager.py", line 381, in __exit__
    raise exception
  File "/media/pomp/data/projects/setup/src/ui/show_main_menu.py", line 88, in show_main_menu
    loader = ptg.YamlLoader()
  File "/home/pomp/.local/lib/python3.10/site-packages/pytermgui/file_loaders.py", line 402, in __init__
    raise RuntimeError(
RuntimeError: YAML implementation module not found. Please install `PyYAML` to use `YamlLoader`.

System information

fatal: not a git repository (or any of the parent directories): .git
PyTermGUI v2.0.0+
Python: 3.10.2
Platform: Linux-5.16.2-arch1-1-x86_64-with-glibc2.33
Git commit: Could not determine due to CalledProcessError:
        Command '['git', 'rev-parse', '--short', 'HEAD']' returned non-zero exit status 128..

Possible cause
Described above

Possible solution
Add PyYAML as pytermgui's dependency.

RIP Zero dependencies :(

[BUG] window reopens minimized

Describe the bug
I have a main window that opens child windows for certain actions. When opening the child window the second time, it opens minimized.

To Reproduce
Steps to reproduce the behavior:

with ptg.WindowManager() as man:
    win2 = ptg.Window(["Close", lambda: *_: man.close(win2)])
    win2.center()
    win1 = ptg.Window(["Open win2", lambda _: man.add(win2)])
    win1.center()
    man.add(win1)
    man.run()
  1. click "Open win2"
  2. click "Close"
  3. click "Open win2"
  4. observe bug

Expected behavior

After opening win2 the second time it should appear the same as the first time.

System information

ptg 3.0.0

[BUG] Documentation site unavailable

Describe the bug
The site https://ptg.bczsalba.com can not be reached.
DNS propagation check fails too: https://dnschecker.org/#A/ptg.bczsalba.com

To Reproduce
Steps to reproduce the behavior:

  1. Open browser
  2. Visit https://ptg.bczsalba.com

Expected behavior
The documentation page should load

Screenshots
Too lazy

System information
Does not have to do with my system.
Checked with multiple browsers, on different device, with VPN, and on tor.
This is clearly an issue on the DNS' side.

Possible cause
Since https://bczsalba.com (without the ptg prefix) does load, this doesn't seem to be a issue where your ownership of the domain has expired. Maybe you messed up the DNS settings for ptg.bczsalba.com

Possible solution
Go to wherever you registered the domain and add the IP address of the server to ptg.bczsalba.com

[REQUEST] Allow printing to the last row of the terminal

I've noticed that doing something like

for row in range(ptg.terminal.height):
    print("something!", pos=(0, row))

Always misses the last row of the terminal. Doing ptg.terminal.height + 1 scrolls the view down one line when printing the last line.

I'm in the process of learning this to replace curses, and I know with curses you can use functions like insstr() or insch() to be able to print right at the edges of the terminal without going out of bounds.

This is definitely something I'd like to see in PTG, it would make full screen apps feel truly "fullscreen"!

Community chat

Is there any community chat for this project? For example a discord server or something similar?

[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] 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

[REQUEST] CSS styling support

Is your feature request related to a problem? Please describe.
No.

Describe the solution you'd like
Add converter function which will take CSS-like rules and converts them to styling features which are supported on terminal.

Describe alternatives you've considered
...

Is this feature present in other TUI products?
Yes. In Textual

Additional context
I know it's hard to implement it. In fact even Textual only supports some rules but it is enough. Even basic rules with suffice.

[BUG] `parser.py` outputs redundant sequences

Describe the bug
When parsing markup, the parser tries to optimize-out redundant sequences. This works when two PLAIN tokens share the exact same sequences, however when the sequence has a new element added it is detected as a wholly unique one, duplicating the sequence for no effect.

To Reproduce

>> import pytermgui as ptg
>> ptg.markup.parse("[bold 141]First [bold 141 italic]First but italic")
'\x1b[1m\x1b[38;5;141mFirst \x1b[1m\x1b[38;5;141m\x1b[3mFirst but italic\x1b[0m'

Expected behavior
The output of the above call should be \x1b[1m\x1b[38;5;141mFirst \x1b[3mFirst but italic\x1b[0m.

System information

PyTermGUI v3.0.0+
Python: 3.9.10
Platform: macOS-12.2.1-arm64-arm-64bit
Git commit: ce27e3c

Possible cause
The "optimizer" part of the parser checks for strict equality, not partial.

Possible solution
Either fixing the possible cause, or leaving it be and running it through an optimize method. That could hinder speed, so the first option is preferred.

[BUG] Overflow.SCROLL may not be working properly

The scrolling example has a box of colors, you can scroll up and down with the arrows or mouse wheel, but the view never moves, the cursor will move down off the screen.

I also tried adding ptg.Overflow.SCROLL to a container that held a label which was more lines than were visible on screen, and scrolling the mouse and arrow keys does nothing at all. I assume if I had a cursor visible, I would see the same thing where the cursor would go off the screen.

My code, just for completeness sake:

        contents = ptg.Container(
            ptg.Label(
                lines,
                parent_align=ptg.HorizontalAlignment.LEFT
            ),
            overflow = ptg.Overflow.SCROLL
        )

Installation fails on Python 3.10/Windows

Cool library! Didn't install easily, though, on WIndows 10 and with Python 3.10:

C:\Users\awood\AppData\Local\Temp\1
λ py -3.10 -m venv pytermgui-env

C:\Users\awood\AppData\Local\Temp\1
λ pytermgui-env\scripts\activate

C:\Users\awood\AppData\Local\Temp\1
(pytermgui-env) λ pip install pytermgui==1.0.1
Looking in indexes: https://pypi.org/simple, http://b******
Collecting pytermgui==1.0.1
  Downloading http://btc-asic-dev01/root/pypi/%2Bf/144/5199ce1d54d82/pytermgui-1.0.1.tar.gz (56 kB)
     |████████████████████████████████| 56 kB 325 kB/s
    ERROR: Command errored out with exit status 1:
     command: 'C:\Users\awood\AppData\Local\Temp\1\pytermgui-env\Scripts\python.exe' -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'C:\\Users\\awood\\AppData\\Local\\Temp\\1\\pip-install-l21qgegv\\pytermgui_0883789d0f7b4af58fb5d9b512057f2b\\setup.py'"'"'; __file__='"'"'C:\\Users\\awood\\AppData\\Local\\Temp\\1\\pip-install-l21qgegv\\pytermgui_0883789d0f7b4af58fb5d9b512057f2b\\setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base 'C:\Users\awood\AppData\Local\Temp\1\pip-pip-egg-info-fv_vf4ds'
         cwd: C:\Users\awood\AppData\Local\Temp\1\pip-install-l21qgegv\pytermgui_0883789d0f7b4af58fb5d9b512057f2b\
    Complete output (17 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "C:\Users\awood\AppData\Local\Temp\1\pip-install-l21qgegv\pytermgui_0883789d0f7b4af58fb5d9b512057f2b\setup.py", line 3, in <module>
        import pytermgui
      File "C:\Users\awood\AppData\Local\Temp\1\pip-install-l21qgegv\pytermgui_0883789d0f7b4af58fb5d9b512057f2b\pytermgui\__init__.py", line 98, in <module>
        from .parser import *
      File "C:\Users\awood\AppData\Local\Temp\1\pip-install-l21qgegv\pytermgui_0883789d0f7b4af58fb5d9b512057f2b\pytermgui\parser.py", line 76, in <module>
        from .ansi_interface import foreground
      File "C:\Users\awood\AppData\Local\Temp\1\pip-install-l21qgegv\pytermgui_0883789d0f7b4af58fb5d9b512057f2b\pytermgui\ansi_interface.py", line 285, in <module>
        terminal = _Terminal()
      File "C:\Users\awood\AppData\Local\Temp\1\pip-install-l21qgegv\pytermgui_0883789d0f7b4af58fb5d9b512057f2b\pytermgui\ansi_interface.py", line 221, in __init__
        self.size: tuple[int, int] = self._get_size()
      File "C:\Users\awood\AppData\Local\Temp\1\pip-install-l21qgegv\pytermgui_0883789d0f7b4af58fb5d9b512057f2b\pytermgui\ansi_interface.py", line 239, in _get_size
        return tuple(val - org for val, org in zip(screen_size(), self.origin))  # type: ignore
      File "C:\Users\awood\AppData\Local\Temp\1\pip-install-l21qgegv\pytermgui_0883789d0f7b4af58fb5d9b512057f2b\pytermgui\ansi_interface.py", line 202, in screen_size
        width, height = get_terminal_size()
    OSError: [WinError 6] The handle is invalid
    ----------------------------------------

Cloning the repo, patching pytermgui.ansi_interface.screen_size to return 0, 0 for errorno in (9, 25) instead of just 25 allowed me to install it, and then seemed to work fine! I'm no terminal expert, but I guess there's no interactive terminal available to pip's install targets.

[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?

[BUG] Non-interpreted ANSI sequence printed in the terminal

Describe the bug
For each invocation of ptg (on the CLI or programmatically), some ANSI sequence is printed on the console:

CLI:

% pdm run ptg --version
^[[4;1890;1072tPyTermGUI 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

Programmatically:

% make docs-serve
INFO     -  Building documentation...
INFO     -  Cleaning site directory
^[[4;1890;1072tINFO     -  Documentation built in 5.20 seconds
INFO     -  [13:37:05] Watching paths for changes: 'docs', 'mkdocs.yml', 'README.md', 'CONTRIBUTING.md', 'CHANGELOG.md',
            'src/markdown_exec'
INFO     -  [13:37:05] Serving on http://127.0.0.1:8000/markdown-exec/
INFO     -  [13:37:06] Browser connected: http://localhost:8000/markdown-exec/gallery/
^CINFO     -  Shutting down...

Expected behavior
No ANSI sequence printed.

Possible cause
Maybe PDM plays a role. I'll try without it.

[BUG] Drag target in WindowManager isn't sticky

Describe the bug
When dragging (LEFT_CLICK & no release) the WM activates a new target every time it moves over one

To Reproduce

  1. Create a WindowManager instance
  2. Add a Window with {"Test": ["Button"]} as on of its element
  3. Try resizing the window from the right, where the button is
  4. The button will keep being activated even though you are trying to resize the window

Expected behavior
The window manager should remember what the last targeted widget was, so when the mouse moves faster than the program can keep up the behaviour isn't undefined.

System information

PyTermGUI v1.1.0+
Python: 3.9.9
Platform: macOS-12.0.1-arm64-arm-64bit
Git commit: 7374236

Possible cause
WindowManager._drag_target is set too often.

Possible solution
Fix possible cause.

[BUG] pip install fails on Python 3.7

Describe the bug
pip installation of PyTermGUI version 4 and above fails on earlier versions than Python 3.8.

To Reproduce
Steps to reproduce the behavior:

  1. Have a Python 3.7
  2. pip install pytermgui
  3. error:
...pytermgui\terminal.py", line 15, in <module>
from functools import cached_property
ImportError: cannot import name 'cached_property' from 'functools' (c:\users\...\python\python37\lib\functools.py)

pip install pytermgui=3.2.1 is the last that works on Python 3.7

Possible cause
functools only introduced cached_property in Python 3.8.

Possible solution
Only use this caching if the installed Python is at least 3.8.
Or, you can change the docs to indicate 3.8+ instead of 3.7+

[REQUEST] better checkbox and radio button styling

Is your feature request related to a problem? Please describe.
No, not really. This is purely a cosmetic improvement.

Describe the solution you'd like
Use a cleaner character for checkbox and radio buttons.
The characters below are taken from the FTXUI project.

Checkbox:
 ☐  ->  ▣
[ ] -> [X]

Radio:
 ○  ->  ◉
( ) -> (*)

Describe alternatives you've considered
There are none other than using other tui libraries with more flexible customization.

Is this feature present in other TUI products?
Yes. In FTXUI.

Additional context
None.

[BUG] Error on launch

Describe the bug
ptg raises error on launch after v4.3.0 update.

To Reproduce
Steps to reproduce the behavior:

  1. Open terminal
  2. run ptg
  3. See error

Expected behavior
Launch ptg.

Screenshots
2022-04-03-095653

System information

fatal: not a git repository (or any parent up to mount point /)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).
PyTermGUI v4.3.0
 
Python: 3.10.4
Platform: Linux-5.16.14-arch1-1-x86_64-with-glibc2.35

[BUG] Splitter doesn't use the full width in some configurations

Describe the bug
The pytermgui.widgets.extra.Splitter class doesn't use the full width on some size configurations, and it becomes 1 character too thin on either odd or even width numbers.

To Reproduce

  1. Create a Window
  2. Add a Splitter with at least two elements
  3. Try resizing the Window while the program is running

Expected behavior
Splitter width should stay the same, regardless of whether the width is even or odd.

System information

PyTermGUI v1.0.1
Python: 3.9.9
Platform: macOS-12.0.1-arm64-arm-64bit
Git commit: ec879a5

Possible cause
The math behind the Splitter width distributions has a bug.

Possible solution
Fixing the Splitter width distribution math.

Inconsistent centering [BUG]

Hello! Twice in one day. I would make a merge request but there's a choice to make, so I defer your preference and backward compatibility.

Describe the bug
Currently, a window is not centered by default but it centers on on terminal.RESIZE. I'm proposing that either windows are centered on manager.add() or not centered on terminal.RESIZE

To Reproduce
1:

with ptg.WindowManager() as manager:
    wm.add(ptg.Window("Hello"))
    wm.run()

2: resize terminal

Possible cause

Containers automatically center on terminal.RESIZE.

pytermgui/widgets/layouts.py:

77        terminal.subscribe(terminal.RESIZE, lambda *_: self.center(self._centered_axis))

Possible solution
1st possibility: disable line 77 above to remove the automatic centering.

2nd possibility:
Center new windows by default.

/pytermgui/window_manager.py

576        window.center()

This might be self._centered but I prefer option 2.

[REQUEST] Add color picker CLI tool

Is your feature request related to a problem? Please describe.
It is very often that I need to reference terminal colors, but the module provides no easy way to do so. You can run code in the interpreter using the ColorPicker name, but it is cumbersome to do.

Describe the solution you'd like
A new app in the ptg CLI: ColorPicker. You could launch it from the application launcher, or ptg --app ColorPicker.

Describe alternatives you've considered
The aforementioned ColorPicker manual use.

Is this feature present in other TUI products?
Not quite sure.

[REQUEST] Support SIGWINCH on Windows

Is your feature request related to a problem? Please describe.
The window size change signal (SIGWINCH) is not built into signal, and PyTermGUI just skips handling it on Windows machines.

Describe the solution you'd like
Some kind of implementation (hopefully up-to-par with UNIX) for resize events.

Describe alternatives you've considered
Creating an asynchronous monitoring loop (#19). Turns out it hangs the program.

Is this feature present in other TUI products?
It is in Textual, not sure about others.

Additional context
We probably have to interact with the windows API (similar to how Textual does it) This is probably a decently sizeable undertaking, and one that I myself cannot take on at the moment.

Any help would be greatly appreciated here!

[REQUEST] Window panel row

Describe the solution you'd like
Add some sort of customizable window panel widget which allows binding actions to panel buttons, like X to close.

Describe alternatives you've considered
Doing it manually: looks out of place and is pretty irregular between projects.

Is this feature present in other TUI products?
Not really, as they don't focus on floating windows. However winman has this.

Additional context
This could be a new widget class, with its own button styling.

[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] `get_markup` sees 2-bit colors as 8-bit ones

When I try to display ANSI text in a Window object, the colors are all wrong: no red or yellow ; cyan shows up as green; everything else looks blue. Any clue why this is happening?

How it looks on terminal:
Screen Shot 2022-05-15 at 12 45 54 AM

How it looks in PTG:
Screen Shot 2022-05-15 at 12 47 36 AM

Source code:

from __future__ import annotations
from pytermgui.parser import MarkupLanguage as ML
import pytermgui as ptg

summary_results = """�[31m============================ �[31m�[1m16 failed�[0m, �[32m16 passed�[0m, �[33m5 skipped�[0m, �[33m6 xfailed�[0m, �[33m3 xpassed�[0m, �[33m22 warnings�[0m, �[31m�[1m9 errors�[0m, �[31m in 12.84s�[0m�[31m =============================�[0m"""

def _configure_widgets() -> None:
    ptg.boxes.SINGLE.set_chars_of(ptg.Window)

def _define_layout() -> ptg.Layout:
    layout = ptg.Layout()
    layout.add_slot("Header", height=1)
    layout.add_break()
    return layout

def main(argv: list[str] | None = None) -> None:
    _configure_widgets()
    with ptg.WindowManager() as manager:
        manager.layout = _define_layout()
        header = ptg.Window(
            ML().get_markup(summary_results),
            # "[app.header] Welcome to PyTermGUI ",
            box="EMPTY",
        )
        manager.add(header)

if __name__ == "__main__":
    main()

[BUG] Documentation is invalid

The documentation snipped here is invalid Python code:

import pytermgui as ptg

with ptg.WindowManager() as manager:
    manager.add(
        ptg.Window()
        + "[wm-title]My first window!",
        + "",
        + ["Exit", lambda *_: manager.exit()],
    )

    manager.run()

Also, the examples on the front page are nice for illustrating the various ways of declaring an interface, but when trying to run them I was taken aback by the fact that a window wouldn't launch. I eventually found the manager.add() function, but it would be nice if that were in the README somewhere so people could quickly try the framework out.

[BUG] InputField appears two cursors when typing

Describe the bug
When I resize the window vertically or set vertical_align of Window to CENTER or BOTTOM, the InputField appeared with two cursors when typing or focusing.

To Reproduce
Steps to reproduce the behavior:

  1. Create a Window with one InputField.
  2. Run the app.
  3. Resize the window vertically.
  4. Click on InputField.
  5. Typing.
  6. See the error.

OR

  1. Go to this replit sandbox: https://replit.com/join/weiqtjcppk-duongvinh
  2. Run the app.
  3. Resize the "Login" window vertically.
  4. Click on InputField.
  5. Typing.
  6. See the error.

Expected behavior
Only one cursor moving on the screen.

Screenshots
pytermgui

System information

PyTermGUI version 6.3.0

System details:
    Python version: 3.10.4
    $TERM:          xterm-256color
    $COLORTERM:     truecolor
    Color support:  ColorSystem.TRUE
    OS Platform:    Linux-5.15.0-37-generic-x86_64-with-glibc2.35

[BUG] documentation example hangs on exit, leaves terminal in dirty state.

Describe the bug
When running the following documentation example, pressing the Exit button exits the window manager but not the application.

import sys

import pytermgui as ptg

with ptg.WindowManager() as manager:
    window = ptg.Window(
        "[wm-title]My first window!",
        "",
        ["Exit", lambda *_: sys.exit()],
    )

    manager.add(window)
    manager.run()

To Reproduce
Steps to reproduce the behavior:

  1. Run the documentation's second examplt
  2. Click on 'Exit'
  3. Note that the application is still running
  4. SIGINT
  5. Try, and fail, to highly text as mouse events are still sent straight to stdin
  6. SIGINT
  7. Type 'reset' and hit enter.

Expected behavior
Press 'Exit', see application cleanly exit with a clean terminal state.

Screenshots
Screenshot

System information

pytermgui version shown

(venv) user@host:~$ pip show pytermgui
Name: pytermgui
Version: 1.0.1
Summary: A simple and robust terminal UI library, written in Python.
Home-page: https://github.com/bczsalba/pytermgui
Author: BcZsalba
Author-email: [email protected]
License: MIT
Location: /home/user/venv/lib/python3.9/site-packages
Requires: 
Required-by:

As requested

(venv) user@host:~$ ptg --version
usage: ptg [-h] [--app {Getch, MarkApp}] [-g] [-m] [-s] [-f FILE] [--print-only]
ptg: error: unrecognized arguments: --version

Additional note: ptg itself does the same thing on exit (re: leaving the terminal dirty)

Reproduces on my PureOS 10 (Debian based), Fedora 35, and Fedora Silverblue Rawhide systems using GNOME Terminal.

The hang behavior persists with XTerm, though the dirty state does not appear to.

Possible cause
There appears to be a lock at play in the traceback. Maybe it isn't released?

Possible solution
N/A

[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] 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.

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.

[REQUEST] Add Container vertical alignment

Is your feature request related to a problem? Please describe.
Currently, vertical alignment within containers is done by hand, which is really annoying and much too stiff in comparison with other parts of the library.

Describe the solution you'd like
Add Container.vertical_alignment policy and enums.ContainerVerticalAlign enum.

Describe alternatives you've considered
Doing it manually: cumbersome.

Is this feature present in other TUI products?
It is present in Rich, and thus in Textual as well. Not sure about nurses2.

Non-selectable button [BUG]

Describe the bug
When you create a container (only tested on the Window widget) with only one button in it, you can't select the button.

To Reproduce

ptg.Window(ptg.Button("Reload?", onclick=lambda *_: manager.alert("Reloading!"))),

Expected behavior
I would expect there to be either:

  • an initial selection, maybe when the window comes into focus, or
  • no initial selection, but pressing a nav key would make the single element the selection

System information

$ ptg --version
PyTermGUI v2.0.0+
Python: 3.10.2
Platform: Linux-4.14.190-22554634-abT860XXU4CUL2-aarch64-with-libc
...

Possible cause
Here, only selecting when selectables_length is 2 or more:

/pytermgui/widgets/layouts.py

761        if self.selectables_length > 1 and _is_nav(key):

Possible solution

Updating to >= 1 would handle this single selectable case, and returning True after the first select will trigger the style update on the button to its 'highlight' class.

/pytermgui/widgets/layouts.py

761         if self.selectables_length >= 1 and _is_nav(key):
762             handled = False
763
764             if self.selected_index is None:
765                 self.select(0)
766                 return True

[SUGGESTION] Add `Window` panel row

I had found the following symbols and thought of sharing them with you as you may find it useful for this project's UI.

— ❐ ✕

The symbols may not look so nice in this issue, but they do look nice in the terminal as shown in the screenshot below:
image

[BUG] getch not working in InputField example

Describe the bug
The InputField example from here doesn't work, produces a NameError: name 'getch' is not defined

To Reproduce
Steps to reproduce the behavior:

  1. Create python file with the contents of the example
  2. Run python file

Expected behavior
keyboard inputs would be printed.
note: ptg -g works as expected

System information

$ ptg --version
PyTermGUI version 6.1.0

System details:
    Python version: 3.10.4
    $TERM:          xterm-256color
    $COLORTERM:     truecolor
    Color support:  ColorSystem.TRUE
    OS Platform:    Linux-5.4.0-109-generic-x86_64-with-glibc2.31

Possible cause
No idea, sorry. I wish I could be of more help. Happy to test anything you should suggest though

Possible solution
As above

[BUG] Missing cached_property dependency on Python 3.7

Describe the bug
cached_property was only introduced in functools in Python 3.8.
To support Python 3.7, you'd need to add "cached_property; python_version < '3.8'" to your setup.py install_requires.

Example PDM traceback

Traceback (most recent call last):
  File "/home/pawamoy/.local/pipx/venvs/pdm/lib/python3.9/site-packages/pep517/in_process/_in_process.py", line 363, in <module>
    main()
  File "/home/pawamoy/.local/pipx/venvs/pdm/lib/python3.9/site-packages/pep517/in_process/_in_process.py", line 345, in main
    json_out['return_val'] = hook(**hook_input['kwargs'])
  File "/home/pawamoy/.local/pipx/venvs/pdm/lib/python3.9/site-packages/pep517/in_process/_in_process.py", line 130, in get_requires_for_build_wheel
    return hook(config_settings)
  File "/tmp/pdm-build-env-6lb9o84s-shared/lib/python3.7/site-packages/setuptools/build_meta.py", line 178, in get_requires_for_build_wheel
    config_settings, requirements=['wheel'])
  File "/tmp/pdm-build-env-6lb9o84s-shared/lib/python3.7/site-packages/setuptools/build_meta.py", line 159, in _get_build_requires
    self.run_setup()
  File "/tmp/pdm-build-env-6lb9o84s-shared/lib/python3.7/site-packages/setuptools/build_meta.py", line 282, in run_setup
    self).run_setup(setup_script=setup_script)
  File "/tmp/pdm-build-env-6lb9o84s-shared/lib/python3.7/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/pdm-build-8bgr4d0i/pytermgui/__init__.py", line 20, in <module>
    from .parser import *
  File "/tmp/pdm-build-8bgr4d0i/pytermgui/parser.py", line 121, in <module>
    from .colors import str_to_color, Color, StandardColor
  File "/tmp/pdm-build-8bgr4d0i/pytermgui/colors.py", line 18, in <module>
    from functools import lru_cache, cached_property
ImportError: cannot import name 'cached_property' from 'functools' (/home/pawamoy/.basher-packages/pyenv/pyenv/versions/3.7.12/lib/python3.7/functools.py)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.