When you open vim or manpage you can't scroll up and check your previous commands, you just stay in this isolated display.
How does this magic work? How to implement it with python?
Or at least say how this thingy is called so I google it properly.
That is called The Alternate Screen Buffer. The terminal emulator provides two modes: primary and alternate; the latter has no scroll back, and when you switch between these buffers the contents in them is preserved. The smcup and rmcup ANSI Escape Sequences are used for switching.
For example, the following displays a FOOBAR banner text for three seconds in the alternate buffer, then switches back to the primary one:
$ tput smcup; banner foobar; sleep 3s; tput rmcup
In Python, you could print the corresponding escape sequences on application start and exit; there may even be a library that does that for you.
Related
From the Python Idle shell, the output from the help() command is not paged. Is there any way to achieve this?
As a workaround I've tried to use pydoc.pager() but with no success. The following works in a normal Python shell started from the terminal but not in the Python Idle shell.
import pydoc
def ihelp(thing):
'''Render text documentation, given an object or a path to an object, and
sends the resulting text to a pager.'''
pydoc.pager(pydoc.render_doc(thing))
Edit: Just to avoid misunderstandings. The ihelp() functions gets the help text both in a terminal Python shell and in the IDLE shell. Paging only works in the terminal shell.
You code works in delivering help output but not in paging it. The pager executes in the user code run process and does not know how to interact with an IDLE shell in a separate gui process. I don't believe you can change this.
To address this issue, IDLE has a new feature, starting with 3.6.7 and 3.7.1 (the release candidates are available now, the final releases will be out in a week or so). IDLE squeezes 'long' output to a button. (By default, 'long' is 50 lines, but user can modify this. Shorted output can be squeezed by right-clicking on it.)
>>> help(int)
[ Squeezed text (241 lines) ] # <== tkinter button
>>>
You can expand the text in place, with a double click, or into the clipboard or a separate non-modal view window, with a right click. A separate window lets one scroll or page up and down in the help entry while writing a statement in the Shell.
I am using the python curses library. I am trying to make an asterisk blink using this code win.addstr(6, 4, "*", curses.A_BLINK) However it does not work on gnome terminal. I tried using it on xterm and it works. It also does not work on the recovery shell. How can I make text blink using the curses library or some other method?
You could make a program (whether with curses or even hardcoded) that draws text on the screen and overwrites it with blanks, with a suitable time delay (if it's too short, it annoys people — see PuTTY for an example of that).
The drawback is that it would "blink" only as long as the program runs, and of course it's a little complicated.
As a shell script, you could do this:
save the stty settings,
change the stty settings to prevent output of carriage return (\r) from being converted to \r\n
print the text, ended with \r
wait a while, e.g., sleep 1
print blanks where you wrote text
wait a while
loop back to the first "print"
on exit, restore the stty settings.
For a curses application - you could make it "blink" by replacing the text, in a similar way. For what it's worth, the xmas example in ncurses-examples uses a combination of window copying and terminal blinking for its animation effects (see C blinkit function and Python translation).
I'm developing a text game using python's wrapper library for curses.
I would like text typed in by the user to be a different color from text output by the game. I've had no problems defining color pairs for the output text, but I can't figure out how to change the input text to display different colors as the user is actively typing.
Currently, I get all input using the getstr() method.
Is this possible with python / curses?
Thanks,
Ian
While you can initialize the Python curses wrapper with echo turned on, if you are using the curses wrapper, if turns echo off initially, e.g.,
# Initialize curses
stdscr = curses.initscr()
# Turn off echoing of keys, and enter cbreak mode,
# where no buffering is performed on keyboard input
curses.noecho()
curses.cbreak()
If curses is not echoing, your program would have to be doing some echoing. But since you're using getstr, that implies you've turned echo on, since the (ncurses) manual page for getstr says
Characters input are echoed only if echo is currently on. In that case, backspace is echoed as deletion of the previous character (typically a left motion).
In this case, you could (depending on how your windows are organized) use wattrset:
Set the “background” set of attributes to attr. This set is initially 0 (no attributes).
The "background" refers to the window attributes, which are merged with attributes associated with text that's added to a window. Since getstr won't have any attributes in the text it adds, setting the window attribute "fixes" your problem. But keep in mind that you'll want to save the original attributes to restore them when getstr is done.
The ncurses curs_attr manual page explains this. The getstr function uses waddch internally (as do printw, addstr), but its manual page does not mention that.
I'm doing a script with a menu-like beginning , and I wanted to know if I could do something like this:
You open the file and it prints this menu :
LOGO
Welcome to script 11 , what would you like to do?
-write a file
-read a file
-create a file
> #input here
You select write ( for example) and it prints this OVER the previous menu intead of printing if after it:
LOGO
Writing a file!
-Select the path:
> #input here
Thanks for the help in advance.
Edit: I didn't want to completely erase the screen( I've seen the other threads about that) but if there is a method to erase only some lines , but the anwers tell me that it isn't possible without external libraries so I'll just clean all the screen and reprint some things, but thanks for all the anwsers
If you are using Linux (or OSX), you can use the curses module.
If you are using windows, use the console module.
If you want to display a multi-line menu, and display an entirely new one after each menu choice, there are only a few ways to do this:
Clear the screen before printing each menu. There are about 69102 questions on SO about how to do this; how to clear the screen in python has links to many of them.
Print out a form feed/page feed. Which will not work on many modern terminals (Windows or Unix), but it rocks on old-school teletypes.
Use terminal control sequences to move the cursor around. This will work on Windows if the cmd terminal is ANSI-enabled (I believe it usually isn't by default), and on everything else if you pick (or look up) the right terminal to send control sequences for. You will also have to make sure to overwrite each character, not just each line. Otherwise, when you overwrite line 2 you'll end up with "Writing a file!pt 11 , what would you like to do?".
Use curses (and your favorite third-party Windows curses port), or some other terminal graphics library, to do this all at a higher level. (Writing separate code using console if it exists—for Windows—and curses otherwise—for almost everything else—is often the simplest way to do this.)
I'd suggest 1 or 4, but those are your options.
I would like to make a single Python script to control curses in two seperate terminal windows. Not curses windows within a single terminal, but two different instances of, say, urxvt in my X window manager.
Something like this:
class myprogam():
controlterm1()
controlterm2()
def controlterm1():
Create a new (could be current) urxvt terminal window.
In the urxvt window setup curses with curses.initscr(), etc.
racergame()
def controlterm2():
Create another urxvt terminal window.
Setup curses.initscr, borders, size, etc. in window, leaving the old one alone.
typewriter()
def racecargame():
Racing game in curses
def typwritter()
Boring program for writing
myprogram()
I see that pseudo-terminal windows are given a name when I use the command "tty", and this gives me a reference to /dev/pts/somenumber, where the first terminal emulator is assigned a zero, then 1, 2, etc for new terminals. Can I use this identifier as a basis to do this?
The script does NOT have to actually load a new instance of urxvt, as I am happy if it can just control one that is already open.
In principle there is no problem with opening multiple devices and doing I/O to them from one script. HOWEVER, most curses software that I've seen assumes it does I/O to the one terminal associated with the program. For example, initscr takes no parameters. It looks at your environment variables to determine your terminal characteristics.
Given that, it might be easier to split your program into two, one running on each terminal, which communicate via message-passing.
The ncurses C API has the newterm function that can be used to initialize the screen. According to the newterm man page:
A program that outputs to more than one terminal should use the newterm routine for each terminal instead of initscr.
However, the python curses module does not implement newterm.