mixmastamyk / console

Comprehensive utility library for terminals. “Better… Stronger… Faster.”
GNU Lesser General Public License v3.0
34 stars 5 forks source link

[Enhancement] Add clear_lines() convenience function #7

Closed matthewgdv closed 4 years ago

matthewgdv commented 4 years ago

I was just thinking it's quite a common task to have to clear a specific number of lines in console apps rather than just the current line, so a convenience function to abstract away the details of it would be super useful.

Thanks for the awesome library. I can't believe I'm only now discovering it!

mixmastamyk commented 4 years ago

Hi, had time to look at this but not completely sure how it would work or the use case. Is there an ANSI sequence to do this that I missed?

Do you mean clear N lines from the bottom of the screen? From the top? Perhaps it means, clear a line then move the cursor up/down and repeat in a loop? Does it return where it started from?

There is a clear_screen(), btw, similar but not exact.

matthewgdv commented 4 years ago

Heya, thanks for taking the time to have a look!

Honestly, I'm not familiar enough with ANSI escape codes to know how exactly this would be implemented, which I think is probably true for a lot of people and it's why I think a clear_lines() function would be useful. If the only way to implement it is to clear the current line, then move the cursor up and repeat in a loop then I suppose that's the way to do it.

But yeah, I just meant clearing N lines from the bottom of the screen. A common use-case for this is a multi-choice prompt that lets the user use the UP/DOWN arrow keys to select an option (with the currently selected option indicated with a [x] while the unselected options are indicated with a [ ]) and ENTER to lock in their choice. In this situation you need to clear as many lines as there are options whenever the user presses UP/DOWN before redrawing the options with the [x] in a new place. In this situation you wouldn't want to clear the whole screen because there might still be information being shown above the choices that user needs in order to make their choice.

For example:

Choose an animal:

[x] Snake
[ ] Dog
[ ] Cat

I'm sure there are other use-cases though, that was just the first one that came to mind.

Does that make sense?

mixmastamyk commented 4 years ago

How does this look, seems to be working for me:

from console import utils
from console.screen import sc

def clear_lines(lines, mode=2):
    ''' Clear the given number of lines above.

        Arguments:
            lines: number of lines above to clear.
            mode:  | 0 | 'forward'  | 'right' - Clear cursor to end of line.
                   | 1 | 'backward' | 'left'  - Clear cursor to beginning of line.
                   | 2 | 'full'               - Clear entire line.
    '''
    mode = utils._mode_map.get(mode, mode)
    for line in range(lines):
        text = sc.erase_line(mode) + sc.up(1)
        utils._write(text)

    return text  # for testing

clear_lines(3)

I'm debating whether something like this should be in another module however. It is getting near the functionality you'd want in a menu or widget library. 🤔

(damn markdown languages!)

matthewgdv commented 4 years ago

Awesome, that's perfect.

Couldn't really say about the library's organisation, but if you've got enough specialised functions to justify reorganizing them into their own module then it probably does make sense to do that.

Thanks again :)