Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
leftbones opened this issue May 15, 2022 · 10 comments
Closed
Labels
Bug Something isn't working

Comments

@leftbones
Copy link

leftbones commented May 15, 2022

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.

@leftbones leftbones added the Bug Something isn't working label May 15, 2022
@bczsalba
Copy link
Owner

Yup, that is a usecase I never really thought about. This method was more intended as a line-by-line printer, and I didn't really think to deal with newlines. Not sure how they should be dealt with, though: I think manipulating the input string without the user's input would become a bit annoying, which is why I just left it to print a single line, and be blissfully unaware of any newlines.

I think you might be interested at the (cursor_at)[https://ptg.bczsalba.com/pytermgui/context_managers.html#cursor_at) method for this actually. Basically it sets up the cursor at the given position, and after every line printed moves one character down, while keeping the horizontal position consistent. Only thing you need to change is add with ptg.cursor_at((10, 1)) as print as a context and print line by line under it.

There also seems to be issues with moving the cursor past the first column, but that's a separate issue.

I think that one is about the terminal's origin position being (1, 1). Printing anything to 0 will have differing behaviour between terminals, AFAIK on Kitty anything printed to y=0 will be completely hidden, and anything at x=0 will just go to 1 instead.

I've been thinking if all the positioning methods should just implicitly apply the origin behind the scenes, as this isn't a very easy to grasp issue. What do you think?

@leftbones
Copy link
Author

That makes sense. I was trying to compare print and write and it seemed that print was meant to take multiple items so I assume it would print them in a "block" starting at the position you passed in. If that's not the intended use, then that's fine.

The idea I had in my head was that block idea, so that it prints the first line at (x, y), then prints every subsequent line at (x, y+1). It is kinda hard to grasp. I'm used to curses, where the origin is (0, 0) and all coordinates are passed in as (y, x) so this whole thing is taking getting used to for me haha.

The issue I was having with the cursor was with the cursor moving functions, it seemed to obey the up and down functions but trying to move to the right didn't do anything at all.

@bczsalba
Copy link
Owner

The issue I was having with the cursor was with the cursor moving functions, it seemed to obey the up and down functions but trying to move to the right didn't do anything at all.

That's really odd, what functions were you using? It should just be giving info to the terminal's API and letting that handle what it does, so I don't see why it wouldn't work. Then again, we are interfacing with terminals: things rarely work properly.

@leftbones
Copy link
Author

That's really odd, what functions were you using? It should just be giving info to the terminal's API and letting that handle what it does, so I don't see why it wouldn't work. Then again, we are interfacing with terminals: things rarely work properly.

In this instance, I was just using the functions included in ansi_interface, I don't think I saved the code but it was something like...

import pytermgui  as ptg

ptg.set_alt_buffer()

while True:
    key == ptg.getch()

    if key == 'h': ptg.cursor_left()
    elif key == 'j': ptg.cursor_down()
    elif key == 'k': ptg.cursor_up()
    elif key == 'l': ptg.cursor_right()
    elif key == '\x1b': break

ptg.unset_alt_buffer()

That was just off the top of my head, it might not actually run, I can't test it at the moment. But basically it would allow me to move the cursor up and down (while doing some awful flickering, likely from redrawing the screen or something) but attempting to move to the left and right did nothing at all.

At one point I also added in ptg.print_to((0, 0), ptg.report_cursor()) to see if anything was happening behind the scenes, and it was not at all what I expected. When moving to the right, for example, the cursor POSITION did move (as reported by report_cursor() but visually, it was stuck on the leftmost column.

My best guess without diving into the code is that the screen is redrawn after each one of these moves, which results in the cursor being placed wherever the last print happened to end. I tried using save_cursor() and restore_cursor() to no avail, I also tried doing the same thing manually by storing the return value of report_cursor() in a variable, then using move_cursor() at the end of the loop to restore it, but that didn't work.

This low level stuff can get really finicky, unfortunately.

@bczsalba
Copy link
Owner

Not sure what your code was exactly, but this works on my terminal (Kitty):

import pytermgui as ptg

ptg.set_alt_buffer()

while True:
    key = ptg.getch()

    if key == "h":
        ptg.cursor_left()
    elif key == "j":
        ptg.cursor_down()
    elif key == "k":
        ptg.cursor_up()
    elif key == "l":
        ptg.cursor_right()
    elif key == "\x1b":
        break

    ptg.terminal.flush()

ptg.unset_alt_buffer()

Note the call to terminal.flush() (which basically just calls sys.stdout.flush()). Without that nothing happens, as by default these functions don't flush the buffer.

Could you try the code above and see what happens? If it still doesn't work we can open a new issue to discuss it, but I think this issue is done for the moment.

@leftbones
Copy link
Author

Noe the call to terminal.flush()

Well don't I feel silly! That's kind of an important thing I completely omitted! Perhaps PTG will work out for my project after all...

@bczsalba
Copy link
Owner

Honestly, I'm still not sure what the issue you faced was, as AFAIK running without flushing should just cause nothing to happen. May be terminal specific, not sure.

@leftbones
Copy link
Author

Yeah, I'm not sure anymore, I wasn't able to reproduce it again. I might have been calling print_to() every update which would have messed things up for sure.

Is there an intended method of adding text to the screen? At the low level, print_to() seems to get the job done fine, but what about at a higher level? As far as adding text to an existing window goes, I haven't quite found the best way.

@bczsalba
Copy link
Owner

I like to use either terminal.write(pos=...), terminal.print(pos=...) or cursor_at, depending on the usecase. There are currently a lot of printing functions in the library for some reason, but they will be consolidated in the future.

@leftbones
Copy link
Author

Ah yeah I had tried those previously but I believe I was also redrawing the windows every update so the prints were ending up underneath the windows. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants