A program I'm writing takes user commands from input(), executes corresponding functions, and displays relevant text.
After about 5 commands-worth of text, the terminal becomes cluttered even when the window is maximized. What I would like to do is clear the terminal after every five commands, but only clear the text that precedes (is above) the fifth command and its output text.
More specifically, after the user has typed in the fifth command, upon pressing Return (entering the command), I want commands 1-4 and their corresponding outputs to clear off the screen but have command 5 and its output remain at the top of the terminal.
For demonstration, here is what I want the screen would look like during this process:
The above becomes the below:
Using the os module and os.system('cls') or os.system('clear') functions will not exactly work in this situation. I don't want to clear all of the text on the screen, just the text before a certain point.
So, how can I do this on Windows with Python?
Note: If the solutions are simple, I would like both a method of obliterating the text so that it cannot be scrolled back up to as well as a method that would allow users to see previous commands and text.
Using simple terminal output, there isn't really a good way to do this. Even the operation of "clearing the screen" is outside what is normally considered simple terminal output, which is why you end up calling an external program to do it.
However, a different way of handling terminal output is to use the curses library. This library allows you extensive control over exactly how your output appears on the screen, and in fact includes functions like deleteln and insdelln to delete lines of text from the screen.
Related
Let's say I want to print a large amount of text, the console will keep only the last lines of the text on screen.
I'm looking for a way to lock a line, lets say line 1 and I want it to be the first line on screen and then scroll down to see the end of the text.
Hope I explained it well enough.
EDIT: Failed to say, that I want to do this in a python script.
I assume you want to do that from a python script, and that's why this is tagged with python.
You want to emulate the behavior of the command less or more. You need to use something like curses for that: https://docs.python.org/3/howto/curses.html
Okay so I am new and still learning all the time and I am trying to wire up a GUI for my code. My code works perfectly in Python IDLE shell and as of so far, works perfectly in my GUI I have created. I have yet to learn
how to multithread processes, I would like multithread all of my functions and redirect output and input from IDLE shell to the three text boxes in my GUI. As of so far, I am pressing my buttons and they work as intended,
all input and output from after pressing a button is in the IDLE shell and my next step is to feed input and output to my text boxes in my GUI, so that my migration from IDLE shell to my GUI is complete and so that my GUI
can 'standalone' independent from the IDLE shell of course. The three text boxes include, 1. for text input, 2.for listing results. and 3. for actively displaying my update features. The program I am making is a file search
method by way of indexing, it works fine in the shell and i am migrating to my GUI. In the shell, when I update say Text files,
the code runs in and out of directories making a list of all text files on the system and saving them in a file, it also does this for video, audio, executable and image files. When the update is executed, files with the
appropriate file extensions for the particular update are displayed in real time in the IDLE shell, streaming down the IDLE shell very fast, this is hopefully the job for text box three, these results will be displayed in
text box three as they are found, for feedback purposes. Text box 1 is user input, the file name to search for, when in IDLE shell, the name entered is searched for in the lists made by my update feature, instead of
scanning the system every time. The result/(s) is then displayed in the shell, this works perfectly and can be opened/played/executed if the user wishes by appending the found path+filename to the appropriate module. This
brings me to text box 2, where in the shell, file results from a search are displayed where they will hopefully now be migrated to text box 2, which is where search results will be displayed from now on.
I am asking for examples how i my case I would achieve this migration from shell to GUI. I will post my code as is and perhaps someone with much more experience can provide some examples on how to re-wire this.
Thank you in advance for any help, Benjamin
When a user runs code with IDLE, output sent to stdout, either with sys.stdout.write or print() with file left as sys.stdout, appears in the tk(inter) Text widget of IDLE's Shell because IDLE replaces the default sys.stdout object with with an object that sends sends strings to the Text widget. Since this involves usually inter-process communication, the code will probably not of must use to you.
What might help is the following: Find in Files (grep) puts found lines in an OutputWindow with a write method that accepts a string and returns the number of characters written. Here is the 3.x version.
def write(self, s, tags=(), mark="insert"):
if isinstance(s, (bytes, bytes)): # convert to string if necessary
s = s.decode(IOBinding.encoding, "replace")
self.text.insert(mark, s, tags) # insert into widget
self.text.see(mark) # make insertion visible
self.text.update() # update widget
return len(s) # return # chars written
I presume you can rewrite this for (py)qt's text widget. The alternative is to use the widget methods directly.
I'm creating a simple two-player board game where each player must place pieces on their own boards. What I would like to do is by either:
opening a new terminal window (regardless which OS the program is run on) for both players so that the board is saved within a variable but the other player cannot scroll up to see where they placed their pieces.
clearing the current terminal completely so that neither player could scroll and see the other player's board. I am aware of the unix 'clear' command but it doesn't achieve the effect I'm after and doesn't work with all OS's (though this might be something that I'll have to sacrifice to get a working solution)
I have tried clearing the screen but haven't been able to completely remove all the text. I don't have a preference; whichever method is easier. Also, if it would be easier to use a different method that I haven't thought of, all other suggestions are welcome. Thanks in advance!
EDIT: Other solutions give the appearance that text has been cleared but a user could still scroll up and see the text that was cleared. I'd like a way to remove any way that a user could see this text.
EDIT 2: Please read the other answers and the comments as they provide a lot of information about the topic as a whole. In particular, thanks to #zondo.
Consider using a portable terminal handling library. They abstract away the system specifica of common tasks like erasing the "screen" (i.e. terminal), or placing output at a specific position on the "screen" (again, meaning the text terminal). However, to use such a library effectively, you often have to switch to its style of generating output on the screen instead of naively printing strings.
curses is one such library (based on the C library ncurses) and included in the Python standard library. To get started, be sure to have a look at the curses tutorial in the official Python documentation.
I'd personally just use this.
import os
os.system("cls" if os.name == "nt" else "clear") #"cls" for Windows, otherwise "clear"
I would recomend a simple ANSI escape code to move the cursor position, Cursor Escape Codes, to the start of the board everytime. There is also an ANSI escape code that completly clears the console though, so you can choose.
If you are on windows you must first import colorama a module that makes windows prompt be able to use the ANSI codes as such:
import colorama # OR: from colorama import init
colorama.init() # AND THEN: init()
So if your board has n rows, after the user input for their turn, you move the cursor UP n rows + however many were required for user input, so if you wrote Input row, col: ... then you would go UP n+1, etc...
A simple example:
numLines = 1
print("Hello world!")
print("\033[<{0}>A".format(numLines), "This came AFTER hello world line")
You may not like this, it's a bit higher level than a basic two player board game, but there is always using some sort of GUI.
I personally like tkinter myself.
You don't want the option of people scrolling up to see printed text, but you can't remove what has been printed, that's like asking a printer to remove ink off a page. It's going to stay there.
Research a GUI interface, and try and make the game in that. Otherwise, you could let me take a stab at creating a explanatory piece of code that shows you how to use tkinter. If you do, link me the game you have so I can understand what you want.
I'm writing a program in curses and sometimes happens that if I leave the program opened and I use other terminal tabs for a while, when I go using the program again it seems like it has refreshed something and something has disappeared... I cannot show pics or screenshots because I haven't understood yet well when and how it happens... Is there a way to prevent or fix this?
screen.getch reads from stdscr, and if it refreshes (due to any change on the screen), will overwrite boxes. You could change that to box.getch, as I did in scroll page by page or line by line using python curses
The manual page for getch says
If the window is not a pad, and it has been moved or modified since the last call to wrefresh, wrefresh will be called before another character is read.
In your sample program you used
screen.keypad( 1 )
which only applies to reading from the standard screen. If you read from the box window, you should set the keypad flag on that:
box.keypad( 1 )
The manual page for keypad says
The default value for keypad is FALSE
that is, it is the default for each window.
A curses program with multiple windows can choose to read from different windows at different times. There is only one input buffer for each screen, but the side-effect of refreshing the current window makes it simpler to manage updates to the windows. (For complicated window stacking order, you would use the panel library rather than rely upon this side-effect).
In Pygame, how can I get graphical input(e.g. clicking exit button) and also get input from the a terminal window simultaneously?
To give you context, my game has a GUI but gets its game commands from a "input()" command. How can I look for input from the command line while also handling graphics?
I'm not sure if this is possible, but if not, what other options do I have for getting text input from the user?
Thanks in advance.
You can't do that, unless you use the input command in a different thread, but then you have to deal with syncronization (which might be what you want or don't want to do).
The way I'd implement this is to create a kind of in-game console. When a special key (e.g. '\') is pressed you make the console appear, and when your application is in that state you interpreter key pressing not as in-game commands but... well, as text. You can print them in the console (using fonts). When a key (e.g "return") is pressed you can make the console disappear and the keys take back their primary functionality.
I did this for my pet-project and it works as a charm. Plus, since you are developing in python you can accept python instructions and use exec to execute them and edit your game "on fhe fly"